From d773347d6e3b38e496641911c70186ef1cfbda10 Mon Sep 17 00:00:00 2001 From: wcjord <32568597+wcjord@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:21:29 -0500 Subject: [PATCH] Morph-repo-2 (#1681) * feat(morphs): repo for getting lang-specific list of morphs * integrated repo into use of morph features and tags * generated * merged with previous push * generated * generated * chore: fix .env file path --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> Co-authored-by: ggurdin --- assets/l10n/intl_en.arb | 8 +- lib/pages/chat/chat.dart | 6 +- lib/pages/chat/chat_view.dart | 4 +- lib/pages/chat_list/chat_list_header.dart | 2 +- .../morph_categories_and_labels.dart | 230 ------------ .../morph_analytics_popup.dart | 351 ------------------ .../analytics_xp_tile.dart | 62 ---- .../vocab_analytics_popup.dart | 278 -------------- .../analytics_details_popup.dart | 87 +++++ .../lemma_usage_dots.dart | 88 +++++ .../lemma_use_example_messages.dart | 157 ++++++++ .../morph_analytics_view.dart | 222 +++++++++++ .../morph_analytics_xp_tile.dart | 8 +- .../vocab_analytics_view.dart | 181 +++++++++ .../vocab_details_view.dart} | 271 ++------------ .../analytics_summary_enum.dart | 0 .../analytics_constants.dart | 0 .../analytics_summary_model.dart | 10 +- .../client_analytics_extension.dart | 0 .../construct_identifier.dart | 16 +- .../construct_level_enum.dart} | 47 ++- .../construct_list_model.dart | 13 +- .../construct_type_enum.dart | 8 +- .../construct_use_model.dart | 20 +- .../construct_use_type_enum.dart | 4 +- .../constructs_event.dart | 4 +- .../constructs_model.dart | 35 +- .../gain_points_animation.dart} | 4 +- .../get_analytics_controller.dart | 14 +- .../learning_skills_enum.dart | 0 .../level_up => analytics_misc}/level_up.dart | 2 +- .../message_analytics_controller.dart | 4 +- .../put_analytics_controller.dart | 8 +- .../room_analytics_extension.dart | 2 +- .../text_loading_shimmer.dart | 0 .../learning_progress_bar.dart | 4 +- .../learning_progress_indicators.dart | 61 ++- .../learning_settings_button.dart | 0 .../analytics_summary/level_badge.dart | 2 +- .../analytics_summary/level_bar_popup.dart | 12 +- .../progress_bar/animated_level_dart.dart | 0 .../progress_bar/level_bar.dart | 4 +- .../progress_bar/progress_bar.dart | 6 +- .../progress_bar/progress_bar_background.dart | 2 +- .../progress_bar/progress_bar_details.dart | 0 .../analytics_summary/progress_indicator.dart | 2 +- .../progress_indicators_enum.dart | 13 +- .../widgets/pangea_chat_list_header.dart | 2 +- .../widgets/class_invitation_buttons.dart | 9 +- .../controllers/it_controller.dart | 4 +- lib/pangea/choreographer/repo/igc_repo.dart | 2 +- .../choreographer/widgets/igc/span_card.dart | 6 +- lib/pangea/choreographer/widgets/it_bar.dart | 6 +- .../common/controllers/pangea_controller.dart | 4 +- lib/pangea/common/network/urls.dart | 2 + .../events/models/pangea_token_model.dart | 30 +- .../models/representation_content_model.dart | 6 +- .../events/utils/message_text_util.dart | 2 +- .../extensions/pangea_room_extension.dart | 6 +- .../{analytics/models => lemmas}/lemma.dart | 0 .../repo => lemmas}/lemma_info_repo.dart | 8 +- .../repo => lemmas}/lemma_info_request.dart | 2 +- .../repo => lemmas}/lemma_info_response.dart | 0 lib/pangea/morphs/default_morph_mapping.dart | 235 ++++++++++++ lib/pangea/morphs/default_ud_mapping.dart | 234 ++++++++++++ .../utils => morphs}/get_grammar_copy.dart | 0 .../morphs/get_icon_for_morph_feature.dart | 57 +++ .../utils => morphs}/get_svg_link.dart | 0 .../morph_analytics_popup.dart | 232 ++++++++++++ .../morph_categories_enum.dart | 0 lib/pangea/morphs/morph_icon.dart | 37 ++ lib/pangea/morphs/morph_models.dart | 95 +++++ lib/pangea/morphs/morph_repo.dart | 110 ++++++ .../parts_of_speech_enum.dart | 0 .../widgets/download_analytics_dialog.dart | 12 +- .../toolbar/enums/activity_type_enum.dart | 6 +- .../models/practice_activity_model.dart | 6 +- .../practice_activity_record_model.dart | 6 +- .../repo/lemma_activity_generator.dart | 2 +- .../lemma_meaning_activity_generator.dart | 12 +- .../repo/morph_activity_generator.dart | 6 +- .../widgets/message_selection_overlay.dart | 2 +- .../toolbar/widgets/message_token_text.dart | 2 +- .../multiple_choice_activity.dart | 4 +- .../practice_activity_card.dart | 10 +- .../word_zoom/lemma_meaning_widget.dart | 8 +- .../widgets/word_zoom/lemma_widget.dart | 2 +- .../morphs/morphological_center_widget.dart | 13 +- .../morphs/morphological_list_item.dart | 26 +- .../morphs/morphological_list_widget.dart | 8 - .../word_zoom/word_zoom_center_widget.dart | 2 +- 91 files changed, 2025 insertions(+), 1443 deletions(-) delete mode 100644 lib/pangea/analytics/constants/morph_categories_and_labels.dart delete mode 100644 lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_popup.dart delete mode 100644 lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/analytics_xp_tile.dart delete mode 100644 lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_analytics_popup.dart create mode 100644 lib/pangea/analytics_details_popup/analytics_details_popup.dart create mode 100644 lib/pangea/analytics_details_popup/lemma_usage_dots.dart create mode 100644 lib/pangea/analytics_details_popup/lemma_use_example_messages.dart create mode 100644 lib/pangea/analytics_details_popup/morph_analytics_view.dart rename lib/pangea/{analytics/widgets/analytics_summary/morph_analytics_popup => analytics_details_popup}/morph_analytics_xp_tile.dart (84%) create mode 100644 lib/pangea/analytics_details_popup/vocab_analytics_view.dart rename lib/pangea/{analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_definition_popup.dart => analytics_details_popup/vocab_details_view.dart} (56%) rename lib/pangea/{analytics/enums => analytics_downloads}/analytics_summary_enum.dart (100%) rename lib/pangea/{analytics/constants => analytics_misc}/analytics_constants.dart (100%) rename lib/pangea/{analytics/models => analytics_misc}/analytics_summary_model.dart (96%) rename lib/pangea/{analytics/extensions => analytics_misc}/client_analytics_extension.dart (100%) rename lib/pangea/{analytics/models => analytics_misc}/construct_identifier.dart (81%) rename lib/pangea/{analytics/enums/lemma_category_enum.dart => analytics_misc/construct_level_enum.dart} (60%) rename lib/pangea/{analytics/models => analytics_misc}/construct_list_model.dart (95%) rename lib/pangea/{analytics/enums => analytics_misc}/construct_type_enum.dart (83%) rename lib/pangea/{analytics/models => analytics_misc}/construct_use_model.dart (74%) rename lib/pangea/{analytics/enums => analytics_misc}/construct_use_type_enum.dart (98%) rename lib/pangea/{analytics/models => analytics_misc}/constructs_event.dart (81%) rename lib/pangea/{analytics/models => analytics_misc}/constructs_model.dart (83%) rename lib/pangea/{analytics/widgets/gain_points.dart => analytics_misc/gain_points_animation.dart} (96%) rename lib/pangea/{analytics/controllers => analytics_misc}/get_analytics_controller.dart (95%) rename lib/pangea/{analytics/enums => analytics_misc}/learning_skills_enum.dart (100%) rename lib/pangea/{analytics/widgets/level_up => analytics_misc}/level_up.dart (98%) rename lib/pangea/{analytics/controllers => analytics_misc}/message_analytics_controller.dart (98%) rename lib/pangea/{analytics/controllers => analytics_misc}/put_analytics_controller.dart (97%) rename lib/pangea/{analytics/extensions => analytics_misc}/room_analytics_extension.dart (99%) rename lib/pangea/{analytics/widgets => analytics_misc}/text_loading_shimmer.dart (100%) rename lib/pangea/{analytics/widgets => }/analytics_summary/learning_progress_bar.dart (85%) rename lib/pangea/{analytics/widgets => }/analytics_summary/learning_progress_indicators.dart (68%) rename lib/pangea/{analytics/widgets => }/analytics_summary/learning_settings_button.dart (100%) rename lib/pangea/{analytics/widgets => }/analytics_summary/level_badge.dart (94%) rename lib/pangea/{analytics/widgets => }/analytics_summary/level_bar_popup.dart (93%) rename lib/pangea/{analytics/widgets => analytics_summary}/progress_bar/animated_level_dart.dart (100%) rename lib/pangea/{analytics/widgets => analytics_summary}/progress_bar/level_bar.dart (89%) rename lib/pangea/{analytics/widgets => analytics_summary}/progress_bar/progress_bar.dart (89%) rename lib/pangea/{analytics/widgets => analytics_summary}/progress_bar/progress_bar_background.dart (90%) rename lib/pangea/{analytics/widgets => analytics_summary}/progress_bar/progress_bar_details.dart (100%) rename lib/pangea/{analytics/widgets => }/analytics_summary/progress_indicator.dart (96%) rename lib/pangea/{analytics/enums => analytics_summary}/progress_indicators_enum.dart (78%) rename lib/pangea/{analytics/models => lemmas}/lemma.dart (100%) rename lib/pangea/{analytics/repo => lemmas}/lemma_info_repo.dart (90%) rename lib/pangea/{analytics/repo => lemmas}/lemma_info_request.dart (94%) rename lib/pangea/{analytics/repo => lemmas}/lemma_info_response.dart (100%) create mode 100644 lib/pangea/morphs/default_morph_mapping.dart create mode 100644 lib/pangea/morphs/default_ud_mapping.dart rename lib/pangea/{analytics/utils => morphs}/get_grammar_copy.dart (100%) create mode 100644 lib/pangea/morphs/get_icon_for_morph_feature.dart rename lib/pangea/{analytics/utils => morphs}/get_svg_link.dart (100%) create mode 100644 lib/pangea/morphs/morph_analytics_popup/morph_analytics_popup.dart rename lib/pangea/{analytics/enums => morphs}/morph_categories_enum.dart (100%) create mode 100644 lib/pangea/morphs/morph_icon.dart create mode 100644 lib/pangea/morphs/morph_models.dart create mode 100644 lib/pangea/morphs/morph_repo.dart rename lib/pangea/{analytics/enums => morphs}/parts_of_speech_enum.dart (100%) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index c515859ebc..988e9c987a 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4782,7 +4782,13 @@ "numberOfLearners": "Number of learners", "mustBeInteger": "Must be an integer e.g. 1, 2, 3, ...", "noBookmarkedActivities": "No bookmarked activities", - "noLemmasFound": "No lemmas found", + "noLemmasFound": "There are no vocabulary with more than {xp} XP. Keep practicing!", + "@noLemmasFound": { + "type": "text", + "placeholders": { + "xp": {} + } + }, "constructUsePvmDesc": "Produced in voice message", "lockedMorphFeature": "Waiting to be unlocked", "leaveSpaceDescription": "The space will be moved to the archive. Other users will be able to see that you have left the chat." diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 0b23705193..cbb724f855 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -29,9 +29,9 @@ import 'package:fluffychat/pages/chat/chat_view.dart'; import 'package:fluffychat/pages/chat/event_info_dialog.dart'; import 'package:fluffychat/pages/chat/recording_dialog.dart'; import 'package:fluffychat/pages/chat_details/chat_details.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/widgets/level_up/level_up.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/level_up.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart'; import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart'; diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 4fc8c37092..08f6fa473d 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -17,8 +17,8 @@ import 'package:fluffychat/pages/chat/chat_event_list.dart'; import 'package:fluffychat/pages/chat/pinned_events.dart'; import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pangea/activity_planner/activity_plan_page_launch_icon_button.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/widgets/gain_points.dart'; +import 'package:fluffychat/pangea/analytics_misc/gain_points_animation.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/chat/widgets/chat_floating_action_button.dart'; import 'package:fluffychat/pangea/chat/widgets/chat_view_background.dart'; import 'package:fluffychat/pangea/chat/widgets/input_bar_wrapper.dart'; diff --git a/lib/pages/chat_list/chat_list_header.dart b/lib/pages/chat_list/chat_list_header.dart index b51e8b212e..d201fce880 100644 --- a/lib/pages/chat_list/chat_list_header.dart +++ b/lib/pages/chat_list/chat_list_header.dart @@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/client_chooser_button.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/learning_progress_indicators.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart'; class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { final ChatListController controller; diff --git a/lib/pangea/analytics/constants/morph_categories_and_labels.dart b/lib/pangea/analytics/constants/morph_categories_and_labels.dart deleted file mode 100644 index a63fc75fb8..0000000000 --- a/lib/pangea/analytics/constants/morph_categories_and_labels.dart +++ /dev/null @@ -1,230 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:material_symbols_icons/symbols.dart'; - -const Map> morphCategoriesAndLabels = { - "pos": [ - "ADJ", - "ADP", - "ADV", - "AFFIX", - "AUX", - "CCONJ", - "DET", - "INTJ", - "NOUN", - "NUM", - "PART", - "PRON", - "PROPN", - "PUNCT", - "SCONJ", - "SPACE", - "SYM", - "VERB", - "X", - ], - "advtype": ["Adverbial", "Tim"], - "aspect": [ - "Imp", - "Perf", - "Prog", - "Hab", - ], - "case": [ - "Nom", - "Acc", - "Dat", - "Gen", - "Voc", - "Abl", - "Loc", - "All", - "Ins", - "Ess", - "Tra", - "Com", - "Par", - "Adv", - "Ref", - "Rel", - "Equ", - "Dis", - "Abs", - "Erg", - "Cau", - "Ben", - "Sub", - "Sup", - "Tem", - "Obl", - "Acc,Dat", - "Acc,Nom", - "Pre", - ], - "conjtype": ["Coord", "Sub", "Cmp"], - "definite": ["Def", "Ind", "Cons"], - "degree": [ - "Pos", - "Cmp", - "Sup", - "Abs", - ], - "evident": ["Fh", "Nfh"], - "foreign": ["Yes"], - "gender": ["Masc", "Fem", "Neut", "Com"], - "mood": [ - "Ind", - "Imp", - "Sub", - "Cnd", - "Opt", - "Jus", - "Adm", - "Des", - "Nec", - "Pot", - "Prp", - "Qot", - "Int", - ], - "nountype": ["Prop", "Comm", "Not_proper"], - "numform": [ - "Digit", - "Word", - "Roman", - "Letter", - ], - "numtype": [ - "Card", - "Ord", - "Mult", - "Frac", - "Sets", - "Range", - "Dist", - ], - "number": [ - "Sing", - "Plur", - "Dual", - "Tri", - "Pauc", - "Grpa", - "Grpl", - "Inv", - ], - "number[psor]": ["Sing", "Plur", "Dual"], - "person": [ - "0", - "1", - "2", - "3", - "4", - ], - "polarity": ["Pos", "Neg"], - "polite": ["Infm", "Form", "Elev", "Humb"], - "poss": ["Yes"], - "prepcase": ["Npr"], - "prontype": [ - "Prs", - "Int", - "Rel", - "Dem", - "Tot", - "Neg", - "Art", - "Emp", - "Exc", - "Ind", - "Rcp", - "Int,Rel", - ], - "punctside": ["Ini", "Fin"], - "puncttype": [ - "Brck", - "Dash", - "Excl", - "Peri", - "Qest", - "Quot", - "Semi", - "Colo", - "Comm", - ], - "reflex": ["Yes"], - "tense": ["Pres", "Past", "Fut", "Imp", "Pqp", "Aor", "Eps", "Prosp"], - "verbform": [ - "Fin", - "Inf", - "Sup", - "Part", - "Conv", - "Vnoun", - "Ger", - "Adn", - "Lng", - ], - "verbtype": ["Mod", "Caus"], - "voice": ["Act", "Mid", "Pass", "Antip", "Cau", "Dir", "Inv", "Rcp", "Caus"], - "x": ["X"], -}; - -// TODO Use the icons that Khue is creating -IconData getIconForMorphFeature(String feature) { - // Define a function to get the icon based on the universal dependency morphological feature (key) - switch (feature.toLowerCase()) { - case 'number': - // google material 123 icon - return Icons.format_list_numbered; - case 'gender': - return Icons.wc; - case 'tense': - return Icons.access_time; - case 'mood': - return Icons.mood; - case 'person': - return Icons.person; - case 'case': - return Icons.format_list_bulleted; - case 'degree': - return Icons.trending_up; - case 'verbform': - return Icons.text_format; - case 'voice': - return Icons.record_voice_over; - case 'aspect': - return Icons.aspect_ratio; - case 'prontype': - return Icons.text_fields; - case 'numtype': - return Icons.format_list_numbered; - case 'poss': - return Icons.account_balance; - case 'reflex': - return Icons.refresh; - case 'foreign': - return Icons.language; - case 'abbr': - return Icons.text_format; - case 'nountype': - return Symbols.abc; - case 'pos': - return Symbols.toys_and_games; - case 'polarity': - return Icons.swap_vert; - case 'definite': - return Icons.check_circle_outline; - case 'prepcase': - return Icons.location_on_outlined; - case 'conjtype': - return Icons.compare_arrows; - default: - return Icons.help_outline; - } -} - -List getLabelsForMorphCategory(String feature) => - morphCategoriesAndLabels[feature.toLowerCase()] ?? []; - -List getMorphCategories() => morphCategoriesAndLabels.keys.toList(); diff --git a/lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_popup.dart b/lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_popup.dart deleted file mode 100644 index bf068be96e..0000000000 --- a/lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_popup.dart +++ /dev/null @@ -1,351 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/constants/morph_categories_and_labels.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_svg_link.dart'; -import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; -import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; -import 'package:fluffychat/utils/color_value.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - -class MorphAnalyticsPopup extends StatelessWidget { - const MorphAnalyticsPopup({ - super.key, - }); - - ConstructListModel get _constructsModel => - MatrixState.pangeaController.getAnalytics.constructListModel; - - Map> get _categoriesToUses => - _constructsModel.categoriesToUses(type: ConstructTypeEnum.morph); - - List>> get _sortedEntries { - final entries = _categoriesToUses.entries.toList(); - // Sort the list with custom logic - entries.sort((a, b) { - // Check if one of the keys is 'Other' - if (a.key.toLowerCase() == 'other') return 1; - if (b.key.toLowerCase() == 'other') return -1; - - // Sort by the length of the list in descending order - final aTotalPoints = a.value.fold( - 0, - (previousValue, element) => previousValue + element.points, - ); - final bTotalPoints = b.value.fold( - 0, - (previousValue, element) => previousValue + element.points, - ); - return bTotalPoints.compareTo(aTotalPoints); - }); - return entries; - } - - @override - Widget build(BuildContext context) { - final availableFeatures = getMorphCategories(); - final List>> morphUses = - List.from(_sortedEntries); - - return FullWidthDialog( - dialogContent: Scaffold( - appBar: AppBar( - title: Text(ConstructTypeEnum.morph.indicator.tooltip(context)), - leading: IconButton( - icon: const Icon(Icons.close), - onPressed: Navigator.of(context).pop, - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: _constructsModel - .constructList(type: ConstructTypeEnum.morph) - .isEmpty - ? Center(child: Text(L10n.of(context).noDataFound)) - : ListView.builder( - itemCount: availableFeatures.length, - itemBuilder: (context, index) { - final category = - index < morphUses.length ? morphUses[index] : null; - final ids = category?.value - .map( - (use) => MorphIdentifier( - morphFeature: category.key, - morphTag: use.lemma, - ), - ) - .toList() ?? - []; - - debugPrint( - "category: ${category?.key}, points: ${category?.value.fold( - 0, - (previousValue, element) => - previousValue + element.points, - )}"); - - return MorphFeatureBox(morphIdentifiers: ids); - }, - ), - ), - ), - maxWidth: 600, - maxHeight: 800, - ); - } -} - -class MorphFeatureBox extends StatelessWidget { - final List morphIdentifiers; - - const MorphFeatureBox({ - super.key, - required this.morphIdentifiers, - }); - - String get _morphFeature => morphIdentifiers.first.morphFeature; - - String _categoryCopy( - String category, - BuildContext context, - ) { - if (category.toLowerCase() == "other") { - return L10n.of(context).other; - } - - return ConstructTypeEnum.morph.getDisplayCopy( - category, - context, - ) ?? - category; - } - - Set get _lockedTags { - final availableLabels = getLabelsForMorphCategory(_morphFeature) - .map((tag) => tag.toLowerCase()) - .toSet(); - final usedLabels = - morphIdentifiers.map((morph) => morph.morphTag.toLowerCase()).toSet(); - return availableLabels.difference(usedLabels); - } - - @override - Widget build(BuildContext context) { - if (morphIdentifiers.isEmpty) { - return Opacity( - opacity: 0.5, - child: Container( - padding: const EdgeInsets.all(24.0), - margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16.0), - color: Theme.of(context).disabledColor, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.lock, size: 24.0), - const SizedBox(width: 24.0), - Text( - L10n.of(context).lockedMorphFeature, - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ); - } - - final allMorphIdentifiers = List.from(morphIdentifiers); - allMorphIdentifiers.addAll( - _lockedTags.map( - (tag) => MorphIdentifier( - morphFeature: _morphFeature, - morphTag: tag, - isLocked: true, - ), - ), - ); - - final theme = Theme.of(context); - - return Container( - padding: const EdgeInsets.all(16.0), - margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16.0), - border: Border.all(color: AppConfig.gold, width: 2), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - spacing: 16.0, - children: [ - SizedBox( - height: 30.0, - width: 30.0, - child: CustomizedSvg( - svgUrl: getMorphSvgLink( - morphFeature: _morphFeature, - context: context, - ), - colorReplacements: theme.brightness == Brightness.dark - ? { - "white": theme.cardColor.hexValue.toString(), - "black": "white", - } - : {}, - errorIcon: Icon(getIconForMorphFeature(_morphFeature)), - ), - ), - Text( - _categoryCopy(_morphFeature, context), - style: theme.textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 16.0), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Wrap( - alignment: WrapAlignment.center, - spacing: 16.0, - runSpacing: 16.0, - children: [ - for (final morph in allMorphIdentifiers) - MorphTagChip(morphIdentifier: morph), - ], - ), - ), - ], - ), - ], - ), - ); - } -} - -class MorphTagChip extends StatelessWidget { - final MorphIdentifier morphIdentifier; - - const MorphTagChip({ - super.key, - required this.morphIdentifier, - }); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - if (morphIdentifier.isLocked) { - return Container( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 24.0, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32.0), - color: theme.disabledColor, - ), - child: SizedBox( - width: 28.0, - height: 28.0, - child: Icon( - Icons.lock, - color: theme.brightness == Brightness.dark - ? Colors.black - : Colors.white, - ), - ), - ); - } - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32.0), - gradient: LinearGradient( - begin: Alignment.topLeft, - colors: [ - Color.alphaBlend( - theme.brightness == Brightness.dark - ? Colors.black.withAlpha(220) - : Colors.white.withAlpha(220), - AppConfig.gold, - ), - AppConfig.gold, - ], - ), - ), - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 8.0, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - spacing: 8.0, - children: [ - SizedBox( - width: 28.0, - height: 28.0, - child: CustomizedSvg( - svgUrl: getMorphSvgLink( - morphFeature: morphIdentifier.morphFeature, - morphTag: morphIdentifier.morphTag, - context: context, - ), - colorReplacements: theme.brightness == Brightness.dark - ? { - "white": theme.cardColor.hexValue.toString(), - "black": "white", - } - : {}, - errorIcon: Icon( - getIconForMorphFeature(morphIdentifier.morphFeature), - ), - ), - ), - Text( - getGrammarCopy( - category: morphIdentifier.morphFeature, - lemma: morphIdentifier.morphTag, - context: context, - ) ?? - morphIdentifier.morphTag, - style: TextStyle( - fontWeight: FontWeight.bold, - color: theme.brightness == Brightness.dark - ? Colors.white - : Colors.black, - ), - ), - ], - ), - ); - } -} - -class MorphIdentifier { - final String morphFeature; - final String morphTag; - final bool isLocked; - - const MorphIdentifier({ - required this.morphFeature, - required this.morphTag, - this.isLocked = false, - }); -} diff --git a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/analytics_xp_tile.dart b/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/analytics_xp_tile.dart deleted file mode 100644 index db180b060c..0000000000 --- a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/analytics_xp_tile.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; - -class ConstructUsesXPTile extends StatelessWidget { - final ConstructUses constructUses; - - const ConstructUsesXPTile( - this.constructUses, { - super.key, - }); - - @override - Widget build(BuildContext context) { - final ProgressIndicatorEnum indicator = - constructUses.constructType == ConstructTypeEnum.morph - ? ProgressIndicatorEnum.morphsUsed - : ProgressIndicatorEnum.wordsUsed; - - return Tooltip( - message: - "${constructUses.points} / ${constructUses.constructType.maxXPPerLemma}", - child: ListTile( - onTap: () {}, - title: Text( - constructUses.constructType == ConstructTypeEnum.morph - ? getGrammarCopy( - category: constructUses.category, - lemma: constructUses.lemma, - context: context, - ) ?? - constructUses.lemma - : constructUses.lemma, - ), - subtitle: Row( - children: [ - Expanded( - child: LinearProgressIndicator( - value: constructUses.points / - constructUses.constructType.maxXPPerLemma, - minHeight: 20, - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: indicator.color(context), - ), - ), - const SizedBox(width: 12), - Text("${constructUses.points}xp"), - ], - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 20, - ), - ), - ); - } -} diff --git a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_analytics_popup.dart b/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_analytics_popup.dart deleted file mode 100644 index 16ada73de1..0000000000 --- a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_analytics_popup.dart +++ /dev/null @@ -1,278 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:collection/collection.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/lemma_category_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_definition_popup.dart'; -import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; -import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - -/// Displays vocab analytics, sorted into categories -/// (flowers, greens, and seeds) by points -class VocabAnalyticsPopup extends StatefulWidget { - const VocabAnalyticsPopup({ - super.key, - }); - - @override - VocabAnalyticsPopupState createState() => VocabAnalyticsPopupState(); -} - -class VocabAnalyticsPopupState extends State { - ConstructListModel get _constructsModel => - MatrixState.pangeaController.getAnalytics.constructListModel; - - /// Sort entries alphabetically, to better detect duplicates - List get _sortedEntries { - final entries = - _constructsModel.constructList(type: ConstructTypeEnum.vocab); - entries - .sort((a, b) => a.lemma.toLowerCase().compareTo(b.lemma.toLowerCase())); - return entries; - } - - ConstructUses? _selectedConstruct; - - void _setSelectedConstruct(ConstructUses? construct) { - if (mounted) { - setState(() { - _selectedConstruct = construct; - }); - } - } - - @override - Widget build(BuildContext context) { - return FullWidthDialog( - dialogContent: _selectedConstruct == null - ? LemmaListDialogContent( - lemmas: _sortedEntries, - onTap: _setSelectedConstruct, - ) - : VocabDefinitionPopup( - construct: _selectedConstruct!, - onClose: () => _setSelectedConstruct(null), - ), - maxWidth: 600, - maxHeight: 800, - ); - } -} - -class VocabChip { - final ConstructUses construct; - final String? displayText; - - VocabChip({ - required this.construct, - this.displayText, - }); -} - -class LemmaListSection extends StatelessWidget { - final LemmaCategoryEnum type; - final List lemmas; - final Function(ConstructUses) onTap; - - const LemmaListSection({ - super.key, - required this.type, - required this.lemmas, - required this.onTap, - }); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(20), - margin: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 16.0), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: type.color, - ), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - CustomizedSvg( - svgUrl: type.svgURL, - colorReplacements: const {}, - errorIcon: Text(type.emoji), - ), - Text( - " ${type.xpString} XP", - style: TextStyle( - fontSize: Theme.of(context).textTheme.bodyLarge?.fontSize, - color: Theme.of(context).colorScheme.onPrimaryFixed, - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: lemmas.isEmpty - ? Text( - L10n.of(context).noLemmasFound, - style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryFixed, - ), - ) - : Wrap( - spacing: 0, - runSpacing: 0, - children: lemmas.mapIndexed((index, lemma) { - return MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () => onTap(lemma.construct), - child: Text( - "${lemma.displayText ?? lemma.construct.lemma}${index < lemmas.length - 1 ? ', ' : ''}", - style: TextStyle( - shadows: [ - Shadow( - color: Theme.of(context) - .colorScheme - .onPrimaryFixed, - offset: const Offset(0, -2.5), - ), - ], - color: Colors.transparent, - decoration: TextDecoration.underline, - decorationStyle: TextDecorationStyle.dotted, - decorationColor: - Theme.of(context).colorScheme.onPrimaryFixed, - decorationThickness: 1, - fontSize: Theme.of(context) - .textTheme - .bodyLarge - ?.fontSize, - ), - ), - ), - ); - }).toList(), - ), - ), - ], - ), - ); - } -} - -class LemmaListDialogContent extends StatelessWidget { - final List lemmas; - final Function(ConstructUses) onTap; - - const LemmaListDialogContent({ - super.key, - required this.lemmas, - required this.onTap, - }); - - @override - Widget build(BuildContext context) { - if (lemmas.isEmpty) { - return Scaffold( - appBar: AppBar( - title: Text(ProgressIndicatorEnum.wordsUsed.tooltip(context)), - leading: IconButton( - icon: const Icon(Icons.close), - onPressed: Navigator.of(context).pop, - ), - // TODO: add search and training buttons? - ), - body: Center(child: Text(L10n.of(context).noDataFound)), - ); - } - - // Get lists of lemmas by category - final List flowerLemmas = []; - final List greenLemmas = []; - final List seedLemmas = []; - - for (int i = 0; i < lemmas.length; i++) { - final construct = lemmas[i]; - if (construct.lemma.isEmpty) { - continue; - } - - final int points = construct.points; - String? displayText; - - // Check if previous or next entry has same lemma as this entry - if ((i > 0 && lemmas[i - 1].lemma.equals(construct.lemma)) || - ((i < lemmas.length - 1 && - lemmas[i + 1].lemma.equals(construct.lemma)))) { - final String pos = getGrammarCopy( - category: "pos", - lemma: construct.category, - context: context, - ) ?? - construct.category; - displayText = "${lemmas[i].lemma} (${pos.toLowerCase()})"; - } - - final lemma = VocabChip( - construct: construct, - displayText: displayText, - ); - - if (points < AnalyticsConstants.xpForGreens) { - seedLemmas.add(lemma); - } else if (points >= AnalyticsConstants.xpForFlower) { - flowerLemmas.add(lemma); - } else { - greenLemmas.add(lemma); - } - } - - // Pass sorted lemmas to background tile widgets - final Widget flowers = LemmaListSection( - type: LemmaCategoryEnum.flowers, - lemmas: flowerLemmas, - onTap: onTap, - ); - - final Widget greens = LemmaListSection( - type: LemmaCategoryEnum.greens, - lemmas: greenLemmas, - onTap: onTap, - ); - - final Widget seeds = LemmaListSection( - type: LemmaCategoryEnum.seeds, - lemmas: seedLemmas, - onTap: onTap, - ); - - return Scaffold( - appBar: AppBar( - title: Text(ProgressIndicatorEnum.wordsUsed.tooltip(context)), - leading: IconButton( - icon: const Icon(Icons.close), - onPressed: Navigator.of(context).pop, - ), - // TODO: add search and training buttons? - ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: ListView( - children: [flowers, greens, seeds], - ), - ), - ); - } -} diff --git a/lib/pangea/analytics_details_popup/analytics_details_popup.dart b/lib/pangea/analytics_details_popup/analytics_details_popup.dart new file mode 100644 index 0000000000..136fc0f67e --- /dev/null +++ b/lib/pangea/analytics_details_popup/analytics_details_popup.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/morph_analytics_view.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_view.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/vocab_details_view.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; + +class AnalyticsPopupWrapper extends StatefulWidget { + AnalyticsPopupWrapper({super.key, this.constructZoom, required this.view}); + + ConstructTypeEnum view; + ConstructIdentifier? constructZoom; + + @override + _AnalyticsPopupWrapperState createState() => _AnalyticsPopupWrapperState(); +} + +class _AnalyticsPopupWrapperState extends State { + ConstructIdentifier? localConstructZoom; + ConstructTypeEnum localView = ConstructTypeEnum.vocab; + + @override + void initState() { + super.initState(); + localView = widget.view; + setConstructZoom(widget.constructZoom); + } + + void setConstructZoom(ConstructIdentifier? id) { + if (id != null && id.type != localView) { + localView = id.type; + } + localConstructZoom = id; + setState(() => {}); + } + + @override + Widget build(BuildContext context) { + return FullWidthDialog( + dialogContent: Scaffold( + appBar: AppBar( + title: Text( + localView == ConstructTypeEnum.morph + ? ConstructTypeEnum.morph.indicator.tooltip(context) + : ConstructTypeEnum.vocab.indicator.tooltip(context), + ), + leading: IconButton( + icon: localConstructZoom == null + ? const Icon(Icons.close) + : const Icon(Icons.arrow_back), + onPressed: localConstructZoom == null + ? () => Navigator.of(context).pop() + : () => setConstructZoom(null), + ), + actions: ConstructTypeEnum.values + .map( + (c) => IconButton( + icon: Icon(c.indicator.icon), + onPressed: () => setState(() { + localView = c; + localConstructZoom = null; + }), + isSelected: localView == c, + color: localView == c + ? Theme.of(context).brightness == Brightness.dark + ? AppConfig.primaryColorLight + : AppConfig.primaryColor + : null, + ), + ) + .toList(), + ), + body: localView == ConstructTypeEnum.morph + ? const MorphAnalyticsView() + : localConstructZoom == null + ? VocabAnalyticsView(onConstructZoom: setConstructZoom) + : VocabDetailsView(constructId: localConstructZoom!), + ), + maxWidth: 600, + maxHeight: 800, + ); + } +} diff --git a/lib/pangea/analytics_details_popup/lemma_usage_dots.dart b/lib/pangea/analytics_details_popup/lemma_usage_dots.dart new file mode 100644 index 0000000000..b572b7db87 --- /dev/null +++ b/lib/pangea/analytics_details_popup/lemma_usage_dots.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; + +class LemmaUsageDots extends StatelessWidget { + final ConstructUses construct; + final LearningSkillsEnum category; + + final String tooltip; + final IconData icon; + + const LemmaUsageDots({ + required this.construct, + required this.category, + required this.tooltip, + required this.icon, + super.key, + }); + + /// Find lemma uses for the given exercise type, to create dot list + List sortedUses(LearningSkillsEnum category) { + final List useList = []; + for (final OneConstructUse use in construct.uses) { + if (use.useType.pointValue == 0) { + continue; + } + // If the use type matches the given category, save to list + // Usage with positive XP is saved as true, else false + if (category == use.useType.skillsEnumType) { + useList.add(use.useType.pointValue > 0); + } + } + return useList; + } + + @override + Widget build(BuildContext context) { + final List dots = []; + for (final bool use in sortedUses(category)) { + dots.add( + Container( + width: 15.0, + height: 15.0, + decoration: BoxDecoration( + color: use ? AppConfig.success : Colors.red, + shape: BoxShape.circle, + ), + ), + ); + } + + final Color textColor = Theme.of(context).brightness != Brightness.light + ? construct.lemmaCategory.color + : construct.lemmaCategory.darkColor; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Tooltip( + triggerMode: TooltipTriggerMode.tap, + message: tooltip, + child: Icon( + icon, + size: 24, + color: textColor.withValues(alpha: 0.7), + ), + ), + const SizedBox(width: 8.0), + Flexible( + child: Wrap( + spacing: 3, + runSpacing: 5, + children: dots, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pangea/analytics_details_popup/lemma_use_example_messages.dart b/lib/pangea/analytics_details_popup/lemma_use_example_messages.dart new file mode 100644 index 0000000000..c458c224b5 --- /dev/null +++ b/lib/pangea/analytics_details_popup/lemma_use_example_messages.dart @@ -0,0 +1,157 @@ +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; +import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +class LemmaUseExampleMessages extends StatelessWidget { + final ConstructUses construct; + + const LemmaUseExampleMessages({ + super.key, + required this.construct, + }); + + Future> _getExampleMessages() async { + final Set examples = {}; + for (final OneConstructUse use in construct.uses) { + if (use.useType.skillsEnumType != LearningSkillsEnum.writing || + use.metadata.eventId == null || + use.form == null || + use.pointValue <= 0) { + continue; + } + final Room? room = MatrixState.pangeaController.matrixState.client + .getRoomById(use.metadata.roomId); + if (room == null) continue; + + Timeline? timeline = room.timeline; + if (room.timeline == null) { + timeline = await room.getTimeline(); + } + + final Event? event = await room.getEventById(use.metadata.eventId!); + if (event == null) continue; + final PangeaMessageEvent pangeaMessageEvent = PangeaMessageEvent( + event: event, + timeline: timeline!, + ownMessage: event.senderId == + MatrixState.pangeaController.matrixState.client.userID, + ); + final tokens = pangeaMessageEvent.messageDisplayRepresentation?.tokens; + if (tokens == null || tokens.isEmpty) continue; + final token = + tokens.firstWhereOrNull((token) => token.text.content == use.form); + if (token == null) continue; + + final int offset = token.text.offset; + examples.add( + ExampleMessage( + message: pangeaMessageEvent.messageDisplayText, + offset: offset, + length: use.form!.length, + ), + ); + if (examples.length > 4) break; + } + + return examples.toList(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _getExampleMessages(), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Align( + alignment: Alignment.topLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: snapshot.data!.map((e) { + return Container( + decoration: BoxDecoration( + color: construct.lemmaCategory.color, + borderRadius: BorderRadius.circular(4), + ), + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + margin: const EdgeInsets.only(bottom: 8), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.columnWidth * 1.5, + ), + child: RichText( + text: TextSpan( + style: TextStyle( + color: Theme.of(context).colorScheme.onPrimaryFixed, + fontSize: AppConfig.fontSizeFactor * + AppConfig.messageFontSize, + ), + children: [ + TextSpan(text: e.message.substring(0, e.offset)), + TextSpan( + text: e.message + .substring(e.offset, e.offset + e.length), + style: const TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: e.message.substring(e.offset + e.length), + ), + ], + ), + ), + ); + }).toList(), + ), + ); + } else { + return const Column( + children: [ + SizedBox(height: 10), + CircularProgressIndicator.adaptive( + strokeWidth: 2, + ), + ], + ); + } + }, + ); + } +} + +class ExampleMessage { + final String message; + final int offset; + final int length; + + ExampleMessage({ + required this.message, + required this.offset, + required this.length, + }); + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is ExampleMessage && + other.message == message && + other.offset == offset && + other.length == length; + } + + @override + int get hashCode => message.hashCode ^ offset.hashCode ^ length.hashCode; +} diff --git a/lib/pangea/analytics_details_popup/morph_analytics_view.dart b/lib/pangea/analytics_details_popup/morph_analytics_view.dart new file mode 100644 index 0000000000..176622b4b2 --- /dev/null +++ b/lib/pangea/analytics_details_popup/morph_analytics_view.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/morphs/morph_icon.dart'; +import 'package:fluffychat/pangea/morphs/morph_models.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import '../morphs/morph_repo.dart'; + +class MorphAnalyticsView extends StatelessWidget { + const MorphAnalyticsView({ + super.key, + }); + + List get availableFeatures => MorphsRepo.get().displayFeatures; + + @override + Widget build(BuildContext context) => Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: ListView.builder( + itemCount: availableFeatures.length, + itemBuilder: (context, index) => + availableFeatures[index].displayTags.isNotEmpty + ? MorphFeatureBox( + morphFeature: availableFeatures[index].feature, + ) + : const SizedBox.shrink(), + ), + ); +} + +class MorphFeatureBox extends StatelessWidget { + final String morphFeature; + + const MorphFeatureBox({ + super.key, + required this.morphFeature, + }); + + // get constructData => MatrixState.pangeaController. + + String _categoryCopy( + String category, + BuildContext context, + ) { + if (category.toLowerCase() == "other") { + return L10n.of(context).other; + } + + return ConstructTypeEnum.morph.getDisplayCopy( + category, + context, + ) ?? + category; + } + + Set get allTags => MorphsRepo.get() + .getDisplayTags(morphFeature) + .map((tag) => tag.toLowerCase()) + .toSet(); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + padding: const EdgeInsets.all(16.0), + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all( + color: Theme.of(context).brightness == Brightness.dark + ? AppConfig.primaryColorLight + : AppConfig.primaryColor, + width: 2, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16.0, + children: [ + SizedBox( + height: 30.0, + width: 30.0, + child: MorphIcon(morphFeature: morphFeature, morphTag: null), + ), + Text( + _categoryCopy(morphFeature, context), + style: theme.textTheme.bodyLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 16.0), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Wrap( + alignment: WrapAlignment.center, + spacing: 16.0, + runSpacing: 16.0, + children: allTags + .map( + (morphTag) => MorphTagChip( + morphFeature: morphFeature, + morphTag: morphTag, + constructAnalytics: MatrixState.pangeaController + .getAnalytics.constructListModel + .getConstructUses( + ConstructIdentifier( + lemma: morphTag, + type: ConstructTypeEnum.morph, + category: morphFeature, + ), + ) ?? + ConstructUses( + lemma: morphTag, + constructType: ConstructTypeEnum.morph, + category: morphFeature, + uses: [], + ), + ), + ) + .sortedBy((chip) => chip.constructAnalytics.points) + .reversed + .toList(), + ), + ), + ], + ), + ], + ), + ); + } +} + +class MorphTagChip extends StatelessWidget { + final String morphFeature; + final String morphTag; + final ConstructUses constructAnalytics; + + const MorphTagChip({ + super.key, + required this.morphFeature, + required this.morphTag, + required this.constructAnalytics, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Opacity( + opacity: constructAnalytics.points > 0 ? 1.0 : 0.3, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(32.0), + gradient: constructAnalytics.points > 0 + ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Colors.transparent, + constructAnalytics.lemmaCategory.color, + ], + ) + : null, + color: constructAnalytics.points > 0 ? null : theme.disabledColor, + ), + padding: const EdgeInsets.symmetric( + vertical: 4.0, + horizontal: 8.0, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 8.0, + children: [ + SizedBox( + width: 28.0, + height: 28.0, + child: constructAnalytics.points > 0 + ? MorphIcon( + morphFeature: morphFeature, + morphTag: morphTag, + ) + : const Icon( + Icons.lock, + color: Colors.white, + ), + ), + Text( + getGrammarCopy( + category: morphFeature, + lemma: morphTag, + context: context, + ) ?? + morphTag, + style: TextStyle( + fontWeight: FontWeight.bold, + color: theme.brightness == Brightness.dark + ? Colors.white + : Colors.black, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_xp_tile.dart b/lib/pangea/analytics_details_popup/morph_analytics_xp_tile.dart similarity index 84% rename from lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_xp_tile.dart rename to lib/pangea/analytics_details_popup/morph_analytics_xp_tile.dart index db180b060c..49e2c74871 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_xp_tile.dart +++ b/lib/pangea/analytics_details_popup/morph_analytics_xp_tile.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; class ConstructUsesXPTile extends StatelessWidget { final ConstructUses constructUses; diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_view.dart b/lib/pangea/analytics_details_popup/vocab_analytics_view.dart new file mode 100644 index 0000000000..33165d2fc3 --- /dev/null +++ b/lib/pangea/analytics_details_popup/vocab_analytics_view.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +/// Displays vocab analytics, sorted into categories +/// (flowers, greens, and seeds) by points +class VocabAnalyticsView extends StatelessWidget { + final void Function(ConstructIdentifier) onConstructZoom; + + const VocabAnalyticsView({ + super.key, + required this.onConstructZoom, + }); + + @override + Widget build(BuildContext context) { + final lemmas = MatrixState.pangeaController.getAnalytics.constructListModel + .constructList(type: ConstructTypeEnum.vocab) + ..sort((a, b) => a.lemma.toLowerCase().compareTo(b.lemma.toLowerCase())); + + final flowerLemmas = []; + final greenLemmas = []; + final seedLemmas = []; + for (int i = 0; i < lemmas.length; i++) { + final construct = lemmas[i]; + if (construct.lemma.isEmpty) continue; + final int points = construct.points; + String? displayText; + // Check if previous or next entry has same lemma as this entry + if ((i > 0 && lemmas[i - 1].lemma.equals(construct.lemma)) || + (i < lemmas.length - 1 && + lemmas[i + 1].lemma.equals(construct.lemma))) { + final pos = getGrammarCopy( + category: "pos", + lemma: construct.category, + context: context, + ) ?? + construct.category; + displayText = "${construct.lemma} (${pos.toLowerCase()})"; + } + final lemma = VocabChip( + construct: construct, + displayText: displayText, + ); + // Sort lemmas into categories + if (points < AnalyticsConstants.xpForGreens) { + seedLemmas.add(lemma); + } else if (points >= AnalyticsConstants.xpForFlower) { + flowerLemmas.add(lemma); + } else { + greenLemmas.add(lemma); + } + } + + final flowers = LemmaListSection( + type: ConstructLevelEnum.flowers, + lemmas: flowerLemmas, + onTap: onConstructZoom, + ); + final greens = LemmaListSection( + type: ConstructLevelEnum.greens, + lemmas: greenLemmas, + onTap: onConstructZoom, + ); + final seeds = LemmaListSection( + type: ConstructLevelEnum.seeds, + lemmas: seedLemmas, + onTap: onConstructZoom, + ); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: ListView( + children: [flowers, greens, seeds], + ), + ); + } +} + +class VocabChip { + final ConstructUses construct; + final String? displayText; + + VocabChip({ + required this.construct, + this.displayText, + }); +} + +class LemmaListSection extends StatelessWidget { + final ConstructLevelEnum type; + final List lemmas; + final Function(ConstructIdentifier) onTap; + + const LemmaListSection({ + super.key, + required this.type, + required this.lemmas, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final fontColor = + theme.brightness == Brightness.dark ? type.color : type.darkColor; + return Container( + padding: const EdgeInsets.all(16.0), + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all(color: type.color, width: 2), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomizedSvg( + svgUrl: type.svgURL, + colorReplacements: const {}, + errorIcon: Text(type.emoji), + ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: lemmas.isEmpty + ? Text( + L10n.of(context).noLemmasFound(type.xpNeeded), + style: TextStyle( + color: fontColor, + fontStyle: FontStyle.italic, + ), + ) + : Wrap( + spacing: 0, + runSpacing: 0, + children: lemmas.mapIndexed((index, lemma) { + return MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () => onTap(lemma.construct.id), + child: Text( + "${lemma.displayText ?? lemma.construct.lemma}${index < lemmas.length - 1 ? ', ' : ''}", + style: TextStyle( + shadows: [ + Shadow( + color: fontColor, + offset: const Offset(0, -2.5), + ), + ], + color: Colors.transparent, + decoration: TextDecoration.underline, + decorationStyle: TextDecorationStyle.dotted, + decorationColor: fontColor, + decorationThickness: 1, + fontSize: theme.textTheme.bodyLarge?.fontSize, + ), + ), + ), + ); + }).toList(), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_definition_popup.dart b/lib/pangea/analytics_details_popup/vocab_details_view.dart similarity index 56% rename from lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_definition_popup.dart rename to lib/pangea/analytics_details_popup/vocab_details_view.dart index 9e22350323..b8e11c165e 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_definition_popup.dart +++ b/lib/pangea/analytics_details_popup/vocab_details_view.dart @@ -1,42 +1,39 @@ import 'package:flutter/material.dart'; -import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/learning_skills_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/lemma_category_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/models/lemma.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_repo.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_request.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_response.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/lemma_usage_dots.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/lemma_use_example_messages.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; -import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; +import 'package:fluffychat/pangea/lemmas/lemma.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_repo.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart'; import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/word_audio_button.dart'; import 'package:fluffychat/widgets/matrix.dart'; /// Displays information about selected lemma, and its usage -class VocabDefinitionPopup extends StatelessWidget { - final ConstructUses construct; - final VoidCallback onClose; +class VocabDetailsView extends StatelessWidget { + final ConstructIdentifier constructId; - const VocabDefinitionPopup({ + const VocabDetailsView({ super.key, - required this.construct, - required this.onClose, + required this.constructId, }); + ConstructUses get construct => constructId.constructUses; + String? get emoji => PangeaToken( text: PangeaTokenText( offset: 0, @@ -101,6 +98,7 @@ class VocabDefinitionPopup extends StatelessWidget { return Scaffold( appBar: AppBar( + leading: const SizedBox(), title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -132,10 +130,10 @@ class VocabDefinitionPopup extends StatelessWidget { ], ), centerTitle: true, - leading: SizedBox( - width: 24, - child: BackButton(onPressed: onClose), - ), + // leading: SizedBox( + // width: 24, + // child: BackButton(onPressed: onClose), + // ), ), body: SingleChildScrollView( child: Padding( @@ -311,226 +309,3 @@ class VocabDefinitionPopup extends StatelessWidget { ); } } - -class LemmaUseExampleMessages extends StatelessWidget { - final ConstructUses construct; - - const LemmaUseExampleMessages({ - super.key, - required this.construct, - }); - - Future> _getExampleMessages() async { - final Set examples = {}; - for (final OneConstructUse use in construct.uses) { - if (use.useType.skillsEnumType != LearningSkillsEnum.writing || - use.metadata.eventId == null || - use.form == null || - use.pointValue <= 0) { - continue; - } - final Room? room = MatrixState.pangeaController.matrixState.client - .getRoomById(use.metadata.roomId); - if (room == null) continue; - - Timeline? timeline = room.timeline; - if (room.timeline == null) { - timeline = await room.getTimeline(); - } - - final Event? event = await room.getEventById(use.metadata.eventId!); - if (event == null) continue; - final PangeaMessageEvent pangeaMessageEvent = PangeaMessageEvent( - event: event, - timeline: timeline!, - ownMessage: event.senderId == - MatrixState.pangeaController.matrixState.client.userID, - ); - final tokens = pangeaMessageEvent.messageDisplayRepresentation?.tokens; - if (tokens == null || tokens.isEmpty) continue; - final token = - tokens.firstWhereOrNull((token) => token.text.content == use.form); - if (token == null) continue; - - final int offset = token.text.offset; - examples.add( - ExampleMessage( - message: pangeaMessageEvent.messageDisplayText, - offset: offset, - length: use.form!.length, - ), - ); - if (examples.length > 4) break; - } - - return examples.toList(); - } - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: _getExampleMessages(), - builder: (context, snapshot) { - if (snapshot.hasData) { - return Align( - alignment: Alignment.topLeft, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: snapshot.data!.map((e) { - return Container( - decoration: BoxDecoration( - color: construct.lemmaCategory.color, - borderRadius: BorderRadius.circular(4), - ), - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - margin: const EdgeInsets.only(bottom: 8), - constraints: const BoxConstraints( - maxWidth: FluffyThemes.columnWidth * 1.5, - ), - child: RichText( - text: TextSpan( - style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryFixed, - fontSize: AppConfig.fontSizeFactor * - AppConfig.messageFontSize, - ), - children: [ - TextSpan(text: e.message.substring(0, e.offset)), - TextSpan( - text: e.message - .substring(e.offset, e.offset + e.length), - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan( - text: e.message.substring(e.offset + e.length), - ), - ], - ), - ), - ); - }).toList(), - ), - ); - } else { - return const Column( - children: [ - SizedBox(height: 10), - CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), - ], - ); - } - }, - ); - } -} - -class LemmaUsageDots extends StatelessWidget { - final ConstructUses construct; - final LearningSkillsEnum category; - - final String tooltip; - final IconData icon; - - const LemmaUsageDots({ - required this.construct, - required this.category, - required this.tooltip, - required this.icon, - super.key, - }); - - /// Find lemma uses for the given exercise type, to create dot list - List sortedUses(LearningSkillsEnum category) { - final List useList = []; - for (final OneConstructUse use in construct.uses) { - if (use.useType.pointValue == 0) { - continue; - } - // If the use type matches the given category, save to list - // Usage with positive XP is saved as true, else false - if (category == use.useType.skillsEnumType) { - useList.add(use.useType.pointValue > 0); - } - } - return useList; - } - - @override - Widget build(BuildContext context) { - final List dots = []; - for (final bool use in sortedUses(category)) { - dots.add( - Container( - width: 15.0, - height: 15.0, - decoration: BoxDecoration( - color: use ? AppConfig.success : Colors.red, - shape: BoxShape.circle, - ), - ), - ); - } - - final Color textColor = Theme.of(context).brightness != Brightness.light - ? construct.lemmaCategory.color - : construct.lemmaCategory.darkColor; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Tooltip( - triggerMode: TooltipTriggerMode.tap, - message: tooltip, - child: Icon( - icon, - size: 24, - color: textColor.withValues(alpha: 0.7), - ), - ), - const SizedBox(width: 8.0), - Flexible( - child: Wrap( - spacing: 3, - runSpacing: 5, - children: dots, - ), - ), - ], - ), - ); - } -} - -class ExampleMessage { - final String message; - final int offset; - final int length; - - ExampleMessage({ - required this.message, - required this.offset, - required this.length, - }); - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is ExampleMessage && - other.message == message && - other.offset == offset && - other.length == length; - } - - @override - int get hashCode => message.hashCode ^ offset.hashCode ^ length.hashCode; -} diff --git a/lib/pangea/analytics/enums/analytics_summary_enum.dart b/lib/pangea/analytics_downloads/analytics_summary_enum.dart similarity index 100% rename from lib/pangea/analytics/enums/analytics_summary_enum.dart rename to lib/pangea/analytics_downloads/analytics_summary_enum.dart diff --git a/lib/pangea/analytics/constants/analytics_constants.dart b/lib/pangea/analytics_misc/analytics_constants.dart similarity index 100% rename from lib/pangea/analytics/constants/analytics_constants.dart rename to lib/pangea/analytics_misc/analytics_constants.dart diff --git a/lib/pangea/analytics/models/analytics_summary_model.dart b/lib/pangea/analytics_misc/analytics_summary_model.dart similarity index 96% rename from lib/pangea/analytics/models/analytics_summary_model.dart rename to lib/pangea/analytics_misc/analytics_summary_model.dart index 85a728113e..be7c579832 100644 --- a/lib/pangea/analytics/models/analytics_summary_model.dart +++ b/lib/pangea/analytics_misc/analytics_summary_model.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/enums/analytics_summary_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_downloads/analytics_summary_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_list_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; class AnalyticsSummaryModel { String username; diff --git a/lib/pangea/analytics/extensions/client_analytics_extension.dart b/lib/pangea/analytics_misc/client_analytics_extension.dart similarity index 100% rename from lib/pangea/analytics/extensions/client_analytics_extension.dart rename to lib/pangea/analytics_misc/client_analytics_extension.dart diff --git a/lib/pangea/analytics/models/construct_identifier.dart b/lib/pangea/analytics_misc/construct_identifier.dart similarity index 81% rename from lib/pangea/analytics/models/construct_identifier.dart rename to lib/pangea/analytics_misc/construct_identifier.dart index f9b488f6d3..84e6c5234a 100644 --- a/lib/pangea/analytics/models/construct_identifier.dart +++ b/lib/pangea/analytics_misc/construct_identifier.dart @@ -5,8 +5,10 @@ import 'package:flutter/foundation.dart'; import 'package:collection/collection.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/widgets/matrix.dart'; class ConstructIdentifier { final String lemma; @@ -89,4 +91,16 @@ class ConstructIdentifier { } String get partialKey => "$lemma-${type.string}"; + + ConstructUses get constructUses => + MatrixState.pangeaController.getAnalytics.constructListModel + .getConstructUses( + this, + ) ?? + ConstructUses( + lemma: lemma, + constructType: ConstructTypeEnum.morph, + category: category, + uses: [], + ); } diff --git a/lib/pangea/analytics/enums/lemma_category_enum.dart b/lib/pangea/analytics_misc/construct_level_enum.dart similarity index 60% rename from lib/pangea/analytics/enums/lemma_category_enum.dart rename to lib/pangea/analytics_misc/construct_level_enum.dart index eb52eb685e..2cac707911 100644 --- a/lib/pangea/analytics/enums/lemma_category_enum.dart +++ b/lib/pangea/analytics_misc/construct_level_enum.dart @@ -1,71 +1,82 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; -enum LemmaCategoryEnum { +enum ConstructLevelEnum { flowers, greens, seeds, } -extension LemmaCategoryExtension on LemmaCategoryEnum { +extension ConstructLevelEnumExt on ConstructLevelEnum { Color get color { switch (this) { - case LemmaCategoryEnum.flowers: + case ConstructLevelEnum.flowers: return Color.lerp(AppConfig.primaryColor, Colors.white, 0.6) ?? AppConfig.primaryColor; - case LemmaCategoryEnum.greens: + case ConstructLevelEnum.greens: return Color.lerp(AppConfig.success, Colors.white, 0.6) ?? AppConfig.success; - case LemmaCategoryEnum.seeds: + case ConstructLevelEnum.seeds: return Color.lerp(AppConfig.gold, Colors.white, 0.6) ?? AppConfig.gold; } } Color get darkColor { switch (this) { - case LemmaCategoryEnum.flowers: + case ConstructLevelEnum.flowers: return Color.lerp(AppConfig.primaryColor, Colors.white, 0.3) ?? AppConfig.primaryColor; - case LemmaCategoryEnum.greens: + case ConstructLevelEnum.greens: return Color.lerp(AppConfig.success, Colors.black, 0.3) ?? AppConfig.success; - case LemmaCategoryEnum.seeds: + case ConstructLevelEnum.seeds: return Color.lerp(AppConfig.gold, Colors.black, 0.3) ?? AppConfig.gold; } } String get svgURL { switch (this) { - case LemmaCategoryEnum.seeds: + case ConstructLevelEnum.seeds: return "${AppConfig.assetsBaseURL}/${AnalyticsConstants.seedSvgFileName}"; - case LemmaCategoryEnum.greens: + case ConstructLevelEnum.greens: return "${AppConfig.assetsBaseURL}/${AnalyticsConstants.leafSvgFileName}"; - case LemmaCategoryEnum.flowers: + case ConstructLevelEnum.flowers: return "${AppConfig.assetsBaseURL}/${AnalyticsConstants.flowerSvgFileName}"; } } String get emoji { switch (this) { - case LemmaCategoryEnum.flowers: + case ConstructLevelEnum.flowers: return AnalyticsConstants.emojiForFlower; - case LemmaCategoryEnum.greens: + case ConstructLevelEnum.greens: return AnalyticsConstants.emojiForGreen; - case LemmaCategoryEnum.seeds: + case ConstructLevelEnum.seeds: return AnalyticsConstants.emojiForSeed; } } String get xpString { switch (this) { - case LemmaCategoryEnum.flowers: + case ConstructLevelEnum.flowers: return ">${AnalyticsConstants.xpForFlower}"; - case LemmaCategoryEnum.greens: + case ConstructLevelEnum.greens: return ">${AnalyticsConstants.xpForGreens}"; - case LemmaCategoryEnum.seeds: + case ConstructLevelEnum.seeds: return "<${AnalyticsConstants.xpForGreens}"; } } + + int get xpNeeded { + switch (this) { + case ConstructLevelEnum.flowers: + return AnalyticsConstants.xpForFlower; + case ConstructLevelEnum.greens: + return AnalyticsConstants.xpForGreens; + case ConstructLevelEnum.seeds: + return 0; + } + } } diff --git a/lib/pangea/analytics/models/construct_list_model.dart b/lib/pangea/analytics_misc/construct_list_model.dart similarity index 95% rename from lib/pangea/analytics/models/construct_list_model.dart rename to lib/pangea/analytics_misc/construct_list_model.dart index 431f1b7cc1..4cf0e3d2e3 100644 --- a/lib/pangea/analytics/models/construct_list_model.dart +++ b/lib/pangea/analytics_misc/construct_list_model.dart @@ -4,13 +4,13 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; /// A wrapper around a list of [OneConstructUse]s, used to simplify /// the process of filtering / sorting / displaying the events. @@ -187,6 +187,7 @@ class ConstructListModel { } } + // TODO; make this non-nullable, returning empty if not found ConstructUses? getConstructUses(ConstructIdentifier identifier) { final partialKey = "${identifier.lemma}-${identifier.type.string}"; diff --git a/lib/pangea/analytics/enums/construct_type_enum.dart b/lib/pangea/analytics_misc/construct_type_enum.dart similarity index 83% rename from lib/pangea/analytics/enums/construct_type_enum.dart rename to lib/pangea/analytics_misc/construct_type_enum.dart index b7896ae8ff..6940786d43 100644 --- a/lib/pangea/analytics/enums/construct_type_enum.dart +++ b/lib/pangea/analytics_misc/construct_type_enum.dart @@ -3,10 +3,10 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; -import 'package:fluffychat/pangea/analytics/enums/morph_categories_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/parts_of_speech_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/morphs/morph_categories_enum.dart'; +import 'package:fluffychat/pangea/morphs/parts_of_speech_enum.dart'; enum ConstructTypeEnum { /// for vocabulary words diff --git a/lib/pangea/analytics/models/construct_use_model.dart b/lib/pangea/analytics_misc/construct_use_model.dart similarity index 74% rename from lib/pangea/analytics/models/construct_use_model.dart rename to lib/pangea/analytics_misc/construct_use_model.dart index eb87922004..c4a6c6eda3 100644 --- a/lib/pangea/analytics/models/construct_use_model.dart +++ b/lib/pangea/analytics_misc/construct_use_model.dart @@ -1,9 +1,9 @@ -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/lemma_category_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; /// One lemma and a list of construct uses for that lemma class ConstructUses { @@ -68,12 +68,12 @@ class ConstructUses { } /// Get the lemma category, based on points - LemmaCategoryEnum get lemmaCategory { + ConstructLevelEnum get lemmaCategory { if (points < AnalyticsConstants.xpForGreens) { - return LemmaCategoryEnum.seeds; + return ConstructLevelEnum.seeds; } else if (points >= AnalyticsConstants.xpForFlower) { - return LemmaCategoryEnum.flowers; + return ConstructLevelEnum.flowers; } - return LemmaCategoryEnum.greens; + return ConstructLevelEnum.greens; } } diff --git a/lib/pangea/analytics/enums/construct_use_type_enum.dart b/lib/pangea/analytics_misc/construct_use_type_enum.dart similarity index 98% rename from lib/pangea/analytics/enums/construct_use_type_enum.dart rename to lib/pangea/analytics_misc/construct_use_type_enum.dart index 75d8685c0d..f6665638be 100644 --- a/lib/pangea/analytics/enums/construct_use_type_enum.dart +++ b/lib/pangea/analytics_misc/construct_use_type_enum.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/enums/analytics_summary_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/learning_skills_enum.dart'; +import 'package:fluffychat/pangea/analytics_downloads/analytics_summary_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; enum ConstructUseTypeEnum { diff --git a/lib/pangea/analytics/models/constructs_event.dart b/lib/pangea/analytics_misc/constructs_event.dart similarity index 81% rename from lib/pangea/analytics/models/constructs_event.dart rename to lib/pangea/analytics_misc/constructs_event.dart index 64b3826f00..b9ffda3aec 100644 --- a/lib/pangea/analytics/models/constructs_event.dart +++ b/lib/pangea/analytics_misc/constructs_event.dart @@ -1,7 +1,7 @@ import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import '../../events/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import '../events/constants/pangea_event_types.dart'; class ConstructAnalyticsEvent { late Event _event; diff --git a/lib/pangea/analytics/models/constructs_model.dart b/lib/pangea/analytics_misc/constructs_model.dart similarity index 83% rename from lib/pangea/analytics/models/constructs_model.dart rename to lib/pangea/analytics_misc/constructs_model.dart index 046e0f3f27..39963bff93 100644 --- a/lib/pangea/analytics/models/constructs_model.dart +++ b/lib/pangea/analytics_misc/constructs_model.dart @@ -4,11 +4,12 @@ import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/analytics/constants/morph_categories_and_labels.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import '../enums/construct_type_enum.dart'; +import 'package:fluffychat/pangea/morphs/morph_models.dart'; +import '../morphs/morph_repo.dart'; +import 'construct_type_enum.dart'; class ConstructAnalyticsModel { List uses; @@ -154,13 +155,15 @@ class OneConstructUse { return category ?? "Other"; } + final MorphFeatuuresAndTags morphs = MorphsRepo.get(); + if (categoryEntry == null) { - return _guessGrammarCategory(json["lemma"]); + return morphs.guessMorphCategory(json["lemma"]); } if ((categoryEntry is List)) { if (categoryEntry.isEmpty) { - return _guessGrammarCategory(json["lemma"]); + return morphs.guessMorphCategory(json["lemma"]); } return categoryEntry.first; } else if (categoryEntry is String) { @@ -170,25 +173,7 @@ class OneConstructUse { debugPrint( "Category entry is not a list or string -${json['cat'] ?? json['categories']}-", ); - return _guessGrammarCategory(json["lemma"]); - } - - static String _guessGrammarCategory(String morphLemma) { - for (final String category in morphCategoriesAndLabels.keys) { - if (morphCategoriesAndLabels[category]!.contains(morphLemma)) { - // debugPrint( - // "found missing construct category for $morphLemma: $category", - // ); - return category; - } - } - ErrorHandler.logError( - m: "Morph construct lemma $morphLemma not found in morph categories and labels", - data: { - "morphLemma": morphLemma, - }, - ); - return "Other"; + return morphs.guessMorphCategory(json["lemma"]); } Room? getRoom(Client client) { diff --git a/lib/pangea/analytics/widgets/gain_points.dart b/lib/pangea/analytics_misc/gain_points_animation.dart similarity index 96% rename from lib/pangea/analytics/widgets/gain_points.dart rename to lib/pangea/analytics_misc/gain_points_animation.dart index bc9ea08d51..0e3bf29e74 100644 --- a/lib/pangea/analytics/widgets/gain_points.dart +++ b/lib/pangea/analytics_misc/gain_points_animation.dart @@ -4,8 +4,8 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/controllers/get_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/bot/utils/bot_style.dart'; import 'package:fluffychat/widgets/matrix.dart'; diff --git a/lib/pangea/analytics/controllers/get_analytics_controller.dart b/lib/pangea/analytics_misc/get_analytics_controller.dart similarity index 95% rename from lib/pangea/analytics/controllers/get_analytics_controller.dart rename to lib/pangea/analytics_misc/get_analytics_controller.dart index 21c266d93c..0fa711aa8f 100644 --- a/lib/pangea/analytics/controllers/get_analytics_controller.dart +++ b/lib/pangea/analytics_misc/get_analytics_controller.dart @@ -6,13 +6,13 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/extensions/client_analytics_extension.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_event.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_list_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/common/constants/local.key.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; diff --git a/lib/pangea/analytics/enums/learning_skills_enum.dart b/lib/pangea/analytics_misc/learning_skills_enum.dart similarity index 100% rename from lib/pangea/analytics/enums/learning_skills_enum.dart rename to lib/pangea/analytics_misc/learning_skills_enum.dart diff --git a/lib/pangea/analytics/widgets/level_up/level_up.dart b/lib/pangea/analytics_misc/level_up.dart similarity index 98% rename from lib/pangea/analytics/widgets/level_up/level_up.dart rename to lib/pangea/analytics_misc/level_up.dart index 078b7c2ba9..b99d70ffa1 100644 --- a/lib/pangea/analytics/widgets/level_up/level_up.dart +++ b/lib/pangea/analytics_misc/level_up.dart @@ -8,7 +8,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:http/http.dart' as http; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; class LevelUpUtil { static void showLevelUpDialog( diff --git a/lib/pangea/analytics/controllers/message_analytics_controller.dart b/lib/pangea/analytics_misc/message_analytics_controller.dart similarity index 98% rename from lib/pangea/analytics/controllers/message_analytics_controller.dart rename to lib/pangea/analytics_misc/message_analytics_controller.dart index 38504fd906..2e17eb15e9 100644 --- a/lib/pangea/analytics/controllers/message_analytics_controller.dart +++ b/lib/pangea/analytics_misc/message_analytics_controller.dart @@ -2,8 +2,8 @@ import 'dart:math'; import 'package:flutter/foundation.dart'; -import 'package:fluffychat/pangea/analytics/controllers/get_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; diff --git a/lib/pangea/analytics/controllers/put_analytics_controller.dart b/lib/pangea/analytics_misc/put_analytics_controller.dart similarity index 97% rename from lib/pangea/analytics/controllers/put_analytics_controller.dart rename to lib/pangea/analytics_misc/put_analytics_controller.dart index 09da119063..d2f53cb426 100644 --- a/lib/pangea/analytics/controllers/put_analytics_controller.dart +++ b/lib/pangea/analytics_misc/put_analytics_controller.dart @@ -4,10 +4,10 @@ import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/extensions/client_analytics_extension.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/common/constants/local.key.dart'; import 'package:fluffychat/pangea/common/controllers/base_controller.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; diff --git a/lib/pangea/analytics/extensions/room_analytics_extension.dart b/lib/pangea/analytics_misc/room_analytics_extension.dart similarity index 99% rename from lib/pangea/analytics/extensions/room_analytics_extension.dart rename to lib/pangea/analytics_misc/room_analytics_extension.dart index 50e2446d5e..41cba617f1 100644 --- a/lib/pangea/analytics/extensions/room_analytics_extension.dart +++ b/lib/pangea/analytics_misc/room_analytics_extension.dart @@ -1,4 +1,4 @@ -part of "../../extensions/pangea_room_extension.dart"; +part of "../extensions/pangea_room_extension.dart"; extension AnalyticsRoomExtension on Room { /// Get next n analytics rooms via the space hierarchy diff --git a/lib/pangea/analytics/widgets/text_loading_shimmer.dart b/lib/pangea/analytics_misc/text_loading_shimmer.dart similarity index 100% rename from lib/pangea/analytics/widgets/text_loading_shimmer.dart rename to lib/pangea/analytics_misc/text_loading_shimmer.dart diff --git a/lib/pangea/analytics/widgets/analytics_summary/learning_progress_bar.dart b/lib/pangea/analytics_summary/learning_progress_bar.dart similarity index 85% rename from lib/pangea/analytics/widgets/analytics_summary/learning_progress_bar.dart rename to lib/pangea/analytics_summary/learning_progress_bar.dart index 3eab58fa75..40d2387f1f 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/learning_progress_bar.dart +++ b/lib/pangea/analytics_summary/learning_progress_bar.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LearningProgressBar extends StatelessWidget { diff --git a/lib/pangea/analytics/widgets/analytics_summary/learning_progress_indicators.dart b/lib/pangea/analytics_summary/learning_progress_indicators.dart similarity index 68% rename from lib/pangea/analytics/widgets/analytics_summary/learning_progress_indicators.dart rename to lib/pangea/analytics_summary/learning_progress_indicators.dart index 9a2548cd8e..2c509bc7ba 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/learning_progress_indicators.dart +++ b/lib/pangea/analytics_summary/learning_progress_indicators.dart @@ -5,16 +5,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/pages/chat_list/client_chooser_button.dart'; -import 'package:fluffychat/pangea/analytics/controllers/get_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/learning_progress_bar.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/learning_settings_button.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/level_badge.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/level_bar_popup.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/morph_analytics_popup/morph_analytics_popup.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/progress_indicator.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/vocab_analytics_popup/vocab_analytics_popup.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_list_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_progress_bar.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_settings_button.dart'; +import 'package:fluffychat/pangea/analytics_summary/level_badge.dart'; +import 'package:fluffychat/pangea/analytics_summary/level_bar_popup.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicator.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -110,30 +110,23 @@ class LearningProgressIndicatorsState l2: userL2?.getDisplayName(context) ?? userL2?.langCode, ), Row( - children: [ - ProgressIndicatorBadge( - points: uniqueLemmas(ProgressIndicatorEnum.wordsUsed), - loading: _loading, - onTap: () { - showDialog( - context: context, - builder: (c) => const VocabAnalyticsPopup(), - ); - }, - indicator: ProgressIndicatorEnum.wordsUsed, - ), - ProgressIndicatorBadge( - points: uniqueLemmas(ProgressIndicatorEnum.morphsUsed), - loading: _loading, - onTap: () { - showDialog( - context: context, - builder: (c) => const MorphAnalyticsPopup(), - ); - }, - indicator: ProgressIndicatorEnum.morphsUsed, - ), - ], + children: ConstructTypeEnum.values + .map( + (c) => ProgressIndicatorBadge( + points: uniqueLemmas(c.indicator), + loading: _loading, + onTap: () { + showDialog( + context: context, + builder: (context) => AnalyticsPopupWrapper( + view: c, + ), + ); + }, + indicator: c.indicator, + ), + ) + .toList(), ), ], ), diff --git a/lib/pangea/analytics/widgets/analytics_summary/learning_settings_button.dart b/lib/pangea/analytics_summary/learning_settings_button.dart similarity index 100% rename from lib/pangea/analytics/widgets/analytics_summary/learning_settings_button.dart rename to lib/pangea/analytics_summary/learning_settings_button.dart diff --git a/lib/pangea/analytics/widgets/analytics_summary/level_badge.dart b/lib/pangea/analytics_summary/level_badge.dart similarity index 94% rename from lib/pangea/analytics/widgets/analytics_summary/level_badge.dart rename to lib/pangea/analytics_summary/level_badge.dart index 8b8629e457..1282c1c411 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/level_badge.dart +++ b/lib/pangea/analytics_summary/level_badge.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/level_bar_popup.dart'; +import 'package:fluffychat/pangea/analytics_summary/level_bar_popup.dart'; import 'package:fluffychat/pangea/common/widgets/pressable_button.dart'; class LevelBadge extends StatelessWidget { diff --git a/lib/pangea/analytics/widgets/analytics_summary/level_bar_popup.dart b/lib/pangea/analytics_summary/level_bar_popup.dart similarity index 93% rename from lib/pangea/analytics/widgets/analytics_summary/level_bar_popup.dart rename to lib/pangea/analytics_summary/level_bar_popup.dart index a1dc222b8e..3601a2acbf 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/level_bar_popup.dart +++ b/lib/pangea/analytics_summary/level_bar_popup.dart @@ -3,12 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/controllers/get_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/learning_progress_bar.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_progress_bar.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LevelBarPopup extends StatelessWidget { diff --git a/lib/pangea/analytics/widgets/progress_bar/animated_level_dart.dart b/lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart similarity index 100% rename from lib/pangea/analytics/widgets/progress_bar/animated_level_dart.dart rename to lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart diff --git a/lib/pangea/analytics/widgets/progress_bar/level_bar.dart b/lib/pangea/analytics_summary/progress_bar/level_bar.dart similarity index 89% rename from lib/pangea/analytics/widgets/progress_bar/level_bar.dart rename to lib/pangea/analytics_summary/progress_bar/level_bar.dart index 588223bf21..33953b4bc3 100644 --- a/lib/pangea/analytics/widgets/progress_bar/level_bar.dart +++ b/lib/pangea/analytics_summary/progress_bar/level_bar.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/animated_level_dart.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/animated_level_dart.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; class LevelBar extends StatefulWidget { final LevelBarDetails details; diff --git a/lib/pangea/analytics/widgets/progress_bar/progress_bar.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar.dart similarity index 89% rename from lib/pangea/analytics/widgets/progress_bar/progress_bar.dart rename to lib/pangea/analytics_summary/progress_bar/progress_bar.dart index a8bda6fd3b..7fac09d3f8 100644 --- a/lib/pangea/analytics/widgets/progress_bar/progress_bar.dart +++ b/lib/pangea/analytics_summary/progress_bar/progress_bar.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/level_bar.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar_background.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/level_bar.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_background.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; // Provide an order list of level indicators, each with it's color // and stream. Also provide an overall width and pointsPerLevel. diff --git a/lib/pangea/analytics/widgets/progress_bar/progress_bar_background.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart similarity index 90% rename from lib/pangea/analytics/widgets/progress_bar/progress_bar_background.dart rename to lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart index f8effcca5a..5c9dabef88 100644 --- a/lib/pangea/analytics/widgets/progress_bar/progress_bar_background.dart +++ b/lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/widgets/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; class ProgressBarBackground extends StatelessWidget { final ProgressBarDetails details; diff --git a/lib/pangea/analytics/widgets/progress_bar/progress_bar_details.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart similarity index 100% rename from lib/pangea/analytics/widgets/progress_bar/progress_bar_details.dart rename to lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart diff --git a/lib/pangea/analytics/widgets/analytics_summary/progress_indicator.dart b/lib/pangea/analytics_summary/progress_indicator.dart similarity index 96% rename from lib/pangea/analytics/widgets/analytics_summary/progress_indicator.dart rename to lib/pangea/analytics_summary/progress_indicator.dart index 5bf71db1fc..9a94b77742 100644 --- a/lib/pangea/analytics/widgets/analytics_summary/progress_indicator.dart +++ b/lib/pangea/analytics_summary/progress_indicator.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/enums/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; import 'package:fluffychat/pangea/common/widgets/pressable_button.dart'; /// A badge that represents one learning progress indicator (i.e., construct uses) diff --git a/lib/pangea/analytics/enums/progress_indicators_enum.dart b/lib/pangea/analytics_summary/progress_indicators_enum.dart similarity index 78% rename from lib/pangea/analytics/enums/progress_indicators_enum.dart rename to lib/pangea/analytics_summary/progress_indicators_enum.dart index d3fd2ad522..bc2dbfce27 100644 --- a/lib/pangea/analytics/enums/progress_indicators_enum.dart +++ b/lib/pangea/analytics_summary/progress_indicators_enum.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; enum ProgressIndicatorEnum { level, @@ -23,6 +23,17 @@ extension ProgressIndicatorsExtension on ProgressIndicatorEnum { } } + IconData get iconSelected { + switch (this) { + case ProgressIndicatorEnum.wordsUsed: + return Symbols.dictionary; + case ProgressIndicatorEnum.morphsUsed: + return Symbols.toys_and_games; + case ProgressIndicatorEnum.level: + return Icons.star; + } + } + static bool isDarkMode(BuildContext context) => Theme.of(context).brightness == Brightness.dark; diff --git a/lib/pangea/chat_list/widgets/pangea_chat_list_header.dart b/lib/pangea/chat_list/widgets/pangea_chat_list_header.dart index c321749485..4604209dd6 100644 --- a/lib/pangea/chat_list/widgets/pangea_chat_list_header.dart +++ b/lib/pangea/chat_list/widgets/pangea_chat_list_header.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; -import 'package:fluffychat/pangea/analytics/widgets/analytics_summary/learning_progress_indicators.dart'; +import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart'; class PangeaChatListHeader extends StatelessWidget implements PreferredSizeWidget { diff --git a/lib/pangea/chat_settings/widgets/class_invitation_buttons.dart b/lib/pangea/chat_settings/widgets/class_invitation_buttons.dart index 4899ed0698..d44cf0e204 100644 --- a/lib/pangea/chat_settings/widgets/class_invitation_buttons.dart +++ b/lib/pangea/chat_settings/widgets/class_invitation_buttons.dart @@ -1,14 +1,15 @@ -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/spaces/constants/space_constants.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; + import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import 'package:universal_html/html.dart' as html; +import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/spaces/constants/space_constants.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import '../../../utils/fluffy_share.dart'; class ClassInvitationButtons extends StatelessWidget { diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 4e33284f13..9c7eaffb45 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -7,8 +7,8 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart'; diff --git a/lib/pangea/choreographer/repo/igc_repo.dart b/lib/pangea/choreographer/repo/igc_repo.dart index 0293d279fe..4cad3c98e9 100644 --- a/lib/pangea/choreographer/repo/igc_repo.dart +++ b/lib/pangea/choreographer/repo/igc_repo.dart @@ -2,7 +2,6 @@ import 'dart:convert'; import 'package:http/http.dart'; -import 'package:fluffychat/pangea/analytics/models/lemma.dart'; import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart'; import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/choreographer/repo/language_detection_request.dart'; @@ -10,6 +9,7 @@ import 'package:fluffychat/pangea/choreographer/repo/span_data_repo.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart'; +import 'package:fluffychat/pangea/lemmas/lemma.dart'; import '../../common/constants/model_keys.dart'; import '../../common/network/requests.dart'; import '../../common/network/urls.dart'; diff --git a/lib/pangea/choreographer/widgets/igc/span_card.dart b/lib/pangea/choreographer/widgets/igc/span_card.dart index 9d3b70c508..e49d726bc5 100644 --- a/lib/pangea/choreographer/widgets/igc/span_card.dart +++ b/lib/pangea/choreographer/widgets/igc/span_card.dart @@ -6,9 +6,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/widgets/gain_points.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/gain_points_animation.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/bot/utils/bot_style.dart'; import 'package:fluffychat/pangea/choreographer/enums/span_data_type.dart'; import 'package:fluffychat/pangea/choreographer/models/span_data.dart'; diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index c5024d3744..cb71417816 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -4,9 +4,9 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/widgets/gain_points.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/gain_points_animation.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/controllers/it_controller.dart'; diff --git a/lib/pangea/common/controllers/pangea_controller.dart b/lib/pangea/common/controllers/pangea_controller.dart index f831e65a46..fe272d5abb 100644 --- a/lib/pangea/common/controllers/pangea_controller.dart +++ b/lib/pangea/common/controllers/pangea_controller.dart @@ -8,8 +8,8 @@ import 'package:get_storage/get_storage.dart'; import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/controllers/get_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart'; import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart'; diff --git a/lib/pangea/common/network/urls.dart b/lib/pangea/common/network/urls.dart index b28b163da8..264943434d 100644 --- a/lib/pangea/common/network/urls.dart +++ b/lib/pangea/common/network/urls.dart @@ -72,6 +72,8 @@ class PApiUrls { static String objectiveList = "${PApiUrls.choreoEndpoint}/objectives"; static String topicList = "${PApiUrls.choreoEndpoint}/topics"; + static String morphFeaturesAndTags = "${PApiUrls.choreoEndpoint}/morphs"; + ///-------------------------------- revenue cat -------------------------- static String rcAppsChoreo = "${PApiUrls.subscriptionEndpoint}/app_ids"; static String rcProductsChoreo = diff --git a/lib/pangea/events/models/pangea_token_model.dart b/lib/pangea/events/models/pangea_token_model.dart index c34bf4637e..7a676a56d6 100644 --- a/lib/pangea/events/models/pangea_token_model.dart +++ b/lib/pangea/events/models/pangea_token_model.dart @@ -5,26 +5,26 @@ import 'package:flutter/foundation.dart'; import 'package:collection/collection.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/analytics/constants/analytics_constants.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/lemma_category_enum.dart'; -import 'package:fluffychat/pangea/analytics/extensions/client_analytics_extension.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_repo.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_request.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; +import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_repo.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/repo/lemma_activity_generator.dart'; import 'package:fluffychat/pangea/toolbar/repo/lemma_meaning_activity_generator.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import '../../analytics/models/lemma.dart'; import '../../common/constants/model_keys.dart'; +import '../../lemmas/lemma.dart'; class PangeaToken { PangeaTokenText text; @@ -624,13 +624,13 @@ class PangeaToken { } } - LemmaCategoryEnum get lemmaXPCategory { + ConstructLevelEnum get lemmaXPCategory { if (vocabConstruct.points >= AnalyticsConstants.xpForFlower) { - return LemmaCategoryEnum.flowers; + return ConstructLevelEnum.flowers; } else if (vocabConstruct.points >= AnalyticsConstants.xpForGreens) { - return LemmaCategoryEnum.greens; + return ConstructLevelEnum.greens; } else { - return LemmaCategoryEnum.seeds; + return ConstructLevelEnum.seeds; } } diff --git a/lib/pangea/events/models/representation_content_model.dart b/lib/pangea/events/models/representation_content_model.dart index 588b8b1266..60cd1b2b8b 100644 --- a/lib/pangea/events/models/representation_content_model.dart +++ b/lib/pangea/events/models/representation_content_model.dart @@ -1,8 +1,8 @@ import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart'; import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; diff --git a/lib/pangea/events/utils/message_text_util.dart b/lib/pangea/events/utils/message_text_util.dart index fd64df563b..825c19fc32 100644 --- a/lib/pangea/events/utils/message_text_util.dart +++ b/lib/pangea/events/utils/message_text_util.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; diff --git a/lib/pangea/extensions/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension.dart index 9077c50f65..7ec9aa2edd 100644 --- a/lib/pangea/extensions/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension.dart @@ -15,8 +15,8 @@ import 'package:matrix/matrix.dart'; import 'package:matrix/src/utils/markdown.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_event.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart'; import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart'; @@ -30,7 +30,7 @@ import '../choreographer/models/choreo_record.dart'; import '../events/constants/pangea_event_types.dart'; import '../events/models/representation_content_model.dart'; -part "../analytics/extensions/room_analytics_extension.dart"; +part "../analytics_misc/room_analytics_extension.dart"; part "room_children_and_parents_extension.dart"; part "room_events_extension.dart"; part "room_information_extension.dart"; diff --git a/lib/pangea/analytics/models/lemma.dart b/lib/pangea/lemmas/lemma.dart similarity index 100% rename from lib/pangea/analytics/models/lemma.dart rename to lib/pangea/lemmas/lemma.dart diff --git a/lib/pangea/analytics/repo/lemma_info_repo.dart b/lib/pangea/lemmas/lemma_info_repo.dart similarity index 90% rename from lib/pangea/analytics/repo/lemma_info_repo.dart rename to lib/pangea/lemmas/lemma_info_repo.dart index aa2adba33f..00e269da10 100644 --- a/lib/pangea/analytics/repo/lemma_info_repo.dart +++ b/lib/pangea/lemmas/lemma_info_repo.dart @@ -6,14 +6,14 @@ import 'package:flutter/foundation.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_request.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_response.dart'; import 'package:fluffychat/pangea/common/network/urls.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/models/content_feedback.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import '../../common/config/environment.dart'; -import '../../common/network/requests.dart'; +import '../common/config/environment.dart'; +import '../common/network/requests.dart'; class LemmaInfoRepo { static final GetStorage _lemmaStorage = GetStorage('lemma_storage'); diff --git a/lib/pangea/analytics/repo/lemma_info_request.dart b/lib/pangea/lemmas/lemma_info_request.dart similarity index 94% rename from lib/pangea/analytics/repo/lemma_info_request.dart rename to lib/pangea/lemmas/lemma_info_request.dart index c9c0c04fab..e973549fdc 100644 --- a/lib/pangea/analytics/repo/lemma_info_request.dart +++ b/lib/pangea/lemmas/lemma_info_request.dart @@ -1,5 +1,5 @@ -import 'package:fluffychat/pangea/analytics/repo/lemma_info_response.dart'; import 'package:fluffychat/pangea/events/models/content_feedback.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; class LemmaInfoRequest { final String lemma; diff --git a/lib/pangea/analytics/repo/lemma_info_response.dart b/lib/pangea/lemmas/lemma_info_response.dart similarity index 100% rename from lib/pangea/analytics/repo/lemma_info_response.dart rename to lib/pangea/lemmas/lemma_info_response.dart diff --git a/lib/pangea/morphs/default_morph_mapping.dart b/lib/pangea/morphs/default_morph_mapping.dart new file mode 100644 index 0000000000..e3d89661ef --- /dev/null +++ b/lib/pangea/morphs/default_morph_mapping.dart @@ -0,0 +1,235 @@ +import 'package:fluffychat/pangea/morphs/morph_models.dart'; + +final MorphFeatuuresAndTags defaultMorphMapping = + MorphFeatuuresAndTags.fromJson({ + "language_code": "default", + "features": [ + { + "feature": "pos", + "tag": [ + "ADJ", + "ADP", + "ADV", + "AFFIX", + "AUX", + "CCONJ", + "DET", + "INTJ", + "NOUN", + "NUM", + "PART", + "PRON", + "PROPN", + "PUNCT", + "SCONJ", + "SPACE", + "SYM", + "VERB", + "X", + ], + }, + { + "feature": "advtype", + "tag": ["Adverbial", "Tim"], + }, + { + "feature": "aspect", + "tag": ["Imp", "Perf", "Prog", "Hab"], + }, + { + "feature": "case", + "tag": [ + "Nom", + "Acc", + "Dat", + "Gen", + "Voc", + "Abl", + "Loc", + "All", + "Ins", + "Ess", + "Tra", + "Com", + "Par", + "Adv", + "Ref", + "Rel", + "Equ", + "Dis", + "Abs", + "Erg", + "Cau", + "Ben", + "Sub", + "Sup", + "Tem", + "Obl", + "Acc,Dat", + "Acc,Nom", + "Pre", + ], + }, + { + "feature": "conjtype", + "tag": ["Coord", "Sub", "Cmp"], + }, + { + "feature": "definite", + "tag": ["Def", "Ind", "Cons"], + }, + { + "feature": "degree", + "tag": ["Pos", "Cmp", "Sup", "Abs"], + }, + { + "feature": "evident", + "tag": ["Fh", "Nfh"], + }, + { + "feature": "foreign", + "tag": ["Yes"], + }, + { + "feature": "gender", + "tag": ["Masc", "Fem", "Neut", "Com"], + }, + { + "feature": "mood", + "tag": [ + "Ind", + "Imp", + "Sub", + "Cnd", + "Opt", + "Jus", + "Adm", + "Des", + "Nec", + "Pot", + "Prp", + "Qot", + "Int", + ], + }, + { + "feature": "nountype", + "tag": ["Prop", "Comm", "Not_proper"], + }, + { + "feature": "numform", + "tag": ["Digit", "Word", "Roman", "Letter"], + }, + { + "feature": "numtype", + "tag": ["Card", "Ord", "Mult", "Frac", "Sets", "Range", "Dist"], + }, + { + "feature": "number", + "tag": ["Sing", "Plur", "Dual", "Tri", "Pauc", "Grpa", "Grpl", "Inv"], + }, + { + "feature": "number[psor]", + "tag": ["Sing", "Plur", "Dual"], + }, + { + "feature": "person", + "tag": ["0", "1", "2", "3", "4"], + }, + { + "feature": "polarity", + "tag": ["Pos", "Neg"], + }, + { + "feature": "polite", + "tag": ["Infm", "Form", "Elev", "Humb"], + }, + { + "feature": "poss", + "tag": ["Yes"], + }, + { + "feature": "prepcase", + "tag": ["Npr"], + }, + { + "feature": "prontype", + "tag": [ + "Prs", + "Int", + "Rel", + "Dem", + "Tot", + "Neg", + "Art", + "Emp", + "Exc", + "Ind", + "Rcp", + "Int,Rel", + ], + }, + { + "feature": "punctside", + "tag": ["Ini", "Fin"], + }, + { + "feature": "puncttype", + "tag": [ + "Brck", + "Dash", + "Excl", + "Peri", + "Qest", + "Quot", + "Semi", + "Colo", + "Comm", + ], + }, + { + "feature": "reflex", + "tag": ["Yes"], + }, + { + "feature": "tense", + "tag": ["Pres", "Past", "Fut", "Imp", "Pqp", "Aor", "Eps", "Prosp"], + }, + { + "feature": "verbform", + "tag": [ + "Fin", + "Inf", + "Sup", + "Part", + "Conv", + "Vnoun", + "Ger", + "Adn", + "Lng", + ], + }, + { + "feature": "verbtype", + "tag": ["Mod", "Caus"], + }, + { + "feature": "voice", + "tag": [ + "Act", + "Mid", + "Pass", + "Antip", + "Cau", + "Dir", + "Inv", + "Rcp", + "Caus", + ], + }, + { + "feature": "x", + "tag": ["X"], + } + ], +}); diff --git a/lib/pangea/morphs/default_ud_mapping.dart b/lib/pangea/morphs/default_ud_mapping.dart new file mode 100644 index 0000000000..a389495b88 --- /dev/null +++ b/lib/pangea/morphs/default_ud_mapping.dart @@ -0,0 +1,234 @@ +import 'package:fluffychat/pangea/morphs/morph_models.dart'; + +final MorphFeatuuresAndTags defaultUDMapping = MorphFeatuuresAndTags.fromJson({ + "language_code": "default", + "features": [ + { + "feature": "pos", + "tag": [ + "ADJ", + "ADP", + "ADV", + "AFFIX", + "AUX", + "CCONJ", + "DET", + "INTJ", + "NOUN", + "NUM", + "PART", + "PRON", + "PROPN", + "PUNCT", + "SCONJ", + "SPACE", + "SYM", + "VERB", + "X", + ], + }, + { + "feature": "advtype", + "tag": ["Adverbial", "Tim"], + }, + { + "feature": "aspect", + "tag": ["Imp", "Perf", "Prog", "Hab"], + }, + { + "feature": "case", + "tag": [ + "Nom", + "Acc", + "Dat", + "Gen", + "Voc", + "Abl", + "Loc", + "All", + "Ins", + "Ess", + "Tra", + "Com", + "Par", + "Adv", + "Ref", + "Rel", + "Equ", + "Dis", + "Abs", + "Erg", + "Cau", + "Ben", + "Sub", + "Sup", + "Tem", + "Obl", + "Acc,Dat", + "Acc,Nom", + "Pre", + ], + }, + { + "feature": "conjtype", + "tag": ["Coord", "Sub", "Cmp"], + }, + { + "feature": "definite", + "tag": ["Def", "Ind", "Cons"], + }, + { + "feature": "degree", + "tag": ["Pos", "Cmp", "Sup", "Abs"], + }, + { + "feature": "evident", + "tag": ["Fh", "Nfh"], + }, + { + "feature": "foreign", + "tag": ["Yes"], + }, + { + "feature": "gender", + "tag": ["Masc", "Fem", "Neut", "Com"], + }, + { + "feature": "mood", + "tag": [ + "Ind", + "Imp", + "Sub", + "Cnd", + "Opt", + "Jus", + "Adm", + "Des", + "Nec", + "Pot", + "Prp", + "Qot", + "Int", + ], + }, + { + "feature": "nountype", + "tag": ["Prop", "Comm", "Not_proper"], + }, + { + "feature": "numform", + "tag": ["Digit", "Word", "Roman", "Letter"], + }, + { + "feature": "numtype", + "tag": ["Card", "Ord", "Mult", "Frac", "Sets", "Range", "Dist"], + }, + { + "feature": "number", + "tag": ["Sing", "Plur", "Dual", "Tri", "Pauc", "Grpa", "Grpl", "Inv"], + }, + { + "feature": "number[psor]", + "tag": ["Sing", "Plur", "Dual"], + }, + { + "feature": "person", + "tag": ["0", "1", "2", "3", "4"], + }, + { + "feature": "polarity", + "tag": ["Pos", "Neg"], + }, + { + "feature": "polite", + "tag": ["Infm", "Form", "Elev", "Humb"], + }, + { + "feature": "poss", + "tag": ["Yes"], + }, + { + "feature": "prepcase", + "tag": ["Npr"], + }, + { + "feature": "prontype", + "tag": [ + "Prs", + "Int", + "Rel", + "Dem", + "Tot", + "Neg", + "Art", + "Emp", + "Exc", + "Ind", + "Rcp", + "Int,Rel", + ], + }, + { + "feature": "punctside", + "tag": ["Ini", "Fin"], + }, + { + "feature": "puncttype", + "tag": [ + "Brck", + "Dash", + "Excl", + "Peri", + "Qest", + "Quot", + "Semi", + "Colo", + "Comm", + ], + }, + { + "feature": "reflex", + "tag": ["Yes"], + }, + { + "feature": "tense", + "tag": ["Pres", "Past", "Fut", "Imp", "Pqp", "Aor", "Eps", "Prosp"], + }, + { + "feature": "verbform", + "tag": [ + "Fin", + "Inf", + "Sup", + "Part", + "Conv", + "Vnoun", + "Ger", + "Adn", + "Lng", + ], + }, + { + "feature": "verbtype", + "tag": ["Mod", "Caus"], + }, + { + "feature": "voice", + "tag": [ + "Act", + "Mid", + "Pass", + "Antip", + "Cau", + "Dir", + "Inv", + "Rcp", + "Caus", + ], + }, + { + "feature": "x", + "tag": ["X"], + } + ], +}); diff --git a/lib/pangea/analytics/utils/get_grammar_copy.dart b/lib/pangea/morphs/get_grammar_copy.dart similarity index 100% rename from lib/pangea/analytics/utils/get_grammar_copy.dart rename to lib/pangea/morphs/get_grammar_copy.dart diff --git a/lib/pangea/morphs/get_icon_for_morph_feature.dart b/lib/pangea/morphs/get_icon_for_morph_feature.dart new file mode 100644 index 0000000000..7c5f43164d --- /dev/null +++ b/lib/pangea/morphs/get_icon_for_morph_feature.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +import 'package:material_symbols_icons/symbols.dart'; + +// TODO Use the icons that Khue is creating +IconData getIconForMorphFeature(String feature) { + // Define a function to get the icon based on the universal dependency morphological feature (key) + switch (feature.toLowerCase()) { + case 'number': + // google material 123 icon + return Icons.format_list_numbered; + case 'gender': + return Icons.wc; + case 'tense': + return Icons.access_time; + case 'mood': + return Icons.mood; + case 'person': + return Icons.person; + case 'case': + return Icons.format_list_bulleted; + case 'degree': + return Icons.trending_up; + case 'verbform': + return Icons.text_format; + case 'voice': + return Icons.record_voice_over; + case 'aspect': + return Icons.aspect_ratio; + case 'prontype': + return Icons.text_fields; + case 'numtype': + return Icons.format_list_numbered; + case 'poss': + return Icons.account_balance; + case 'reflex': + return Icons.refresh; + case 'foreign': + return Icons.language; + case 'abbr': + return Icons.text_format; + case 'nountype': + return Symbols.abc; + case 'pos': + return Symbols.toys_and_games; + case 'polarity': + return Icons.swap_vert; + case 'definite': + return Icons.check_circle_outline; + case 'prepcase': + return Icons.location_on_outlined; + case 'conjtype': + return Icons.compare_arrows; + default: + return Icons.help_outline; + } +} diff --git a/lib/pangea/analytics/utils/get_svg_link.dart b/lib/pangea/morphs/get_svg_link.dart similarity index 100% rename from lib/pangea/analytics/utils/get_svg_link.dart rename to lib/pangea/morphs/get_svg_link.dart diff --git a/lib/pangea/morphs/morph_analytics_popup/morph_analytics_popup.dart b/lib/pangea/morphs/morph_analytics_popup/morph_analytics_popup.dart new file mode 100644 index 0000000000..28a065bf5c --- /dev/null +++ b/lib/pangea/morphs/morph_analytics_popup/morph_analytics_popup.dart @@ -0,0 +1,232 @@ +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/morphs/morph_icon.dart'; +import 'package:fluffychat/pangea/morphs/morph_models.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import '../../morphs/morph_repo.dart'; + +class MorphAnalyticsPopup extends StatelessWidget { + const MorphAnalyticsPopup({ + super.key, + }); + + List get availableFeatures => MorphsRepo.get().displayFeatures; + + @override + Widget build(BuildContext context) => FullWidthDialog( + dialogContent: Scaffold( + appBar: AppBar( + title: Text(ConstructTypeEnum.morph.indicator.tooltip(context)), + leading: IconButton( + icon: const Icon(Icons.close), + onPressed: Navigator.of(context).pop, + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: ListView.builder( + itemCount: availableFeatures.length, + itemBuilder: (context, index) => + availableFeatures[index].displayTags.isNotEmpty + ? MorphFeatureBox( + morphFeature: availableFeatures[index].feature, + ) + : const SizedBox.shrink(), + ), + ), + ), + maxWidth: 600, + maxHeight: 800, + ); +} + +class MorphFeatureBox extends StatelessWidget { + final String morphFeature; + + const MorphFeatureBox({ + super.key, + required this.morphFeature, + }); + + // get constructData => MatrixState.pangeaController. + + String _categoryCopy( + String category, + BuildContext context, + ) { + if (category.toLowerCase() == "other") { + return L10n.of(context).other; + } + + return ConstructTypeEnum.morph.getDisplayCopy( + category, + context, + ) ?? + category; + } + + Set get allTags => MorphsRepo.get() + .getDisplayTags(morphFeature) + .map((tag) => tag.toLowerCase()) + .toSet(); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + padding: const EdgeInsets.all(16.0), + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all(color: AppConfig.gold.withAlpha(100), width: 2), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 16.0, + children: [ + SizedBox( + height: 30.0, + width: 30.0, + child: MorphIcon(morphFeature: morphFeature, morphTag: null), + ), + Text( + _categoryCopy(morphFeature, context), + style: theme.textTheme.bodyLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 16.0), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Wrap( + alignment: WrapAlignment.center, + spacing: 16.0, + runSpacing: 16.0, + children: allTags + .map( + (morphTag) => MorphTagChip( + morphFeature: morphFeature, + morphTag: morphTag, + constructAnalytics: MatrixState.pangeaController + .getAnalytics.constructListModel + .getConstructUses( + ConstructIdentifier( + lemma: morphTag, + type: ConstructTypeEnum.morph, + category: morphFeature, + ), + ) ?? + ConstructUses( + lemma: morphTag, + constructType: ConstructTypeEnum.morph, + category: morphFeature, + uses: [], + ), + ), + ) + .sortedBy((chip) => chip.constructAnalytics.points) + .reversed + .toList(), + ), + ), + ], + ), + ], + ), + ); + } +} + +class MorphTagChip extends StatelessWidget { + final String morphFeature; + final String morphTag; + final ConstructUses constructAnalytics; + + const MorphTagChip({ + super.key, + required this.morphFeature, + required this.morphTag, + required this.constructAnalytics, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Opacity( + opacity: constructAnalytics.points > 0 ? 1.0 : 0.3, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(32.0), + gradient: constructAnalytics.points > 0 + ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Colors.transparent, + constructAnalytics.lemmaCategory.color, + ], + ) + : null, + color: constructAnalytics.points > 0 ? null : theme.disabledColor, + ), + padding: const EdgeInsets.symmetric( + vertical: 4.0, + horizontal: 8.0, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 8.0, + children: [ + SizedBox( + width: 28.0, + height: 28.0, + child: constructAnalytics.points > 0 + ? MorphIcon( + morphFeature: morphFeature, + morphTag: morphTag, + ) + : const Icon( + Icons.lock, + color: Colors.white, + ), + ), + Text( + getGrammarCopy( + category: morphFeature, + lemma: morphTag, + context: context, + ) ?? + morphTag, + style: TextStyle( + fontWeight: FontWeight.bold, + color: theme.brightness == Brightness.dark + ? Colors.white + : Colors.black, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pangea/analytics/enums/morph_categories_enum.dart b/lib/pangea/morphs/morph_categories_enum.dart similarity index 100% rename from lib/pangea/analytics/enums/morph_categories_enum.dart rename to lib/pangea/morphs/morph_categories_enum.dart diff --git a/lib/pangea/morphs/morph_icon.dart b/lib/pangea/morphs/morph_icon.dart new file mode 100644 index 0000000000..b4b27500cf --- /dev/null +++ b/lib/pangea/morphs/morph_icon.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; +import 'package:fluffychat/pangea/morphs/get_icon_for_morph_feature.dart'; +import 'package:fluffychat/pangea/morphs/get_svg_link.dart'; +import 'package:fluffychat/utils/color_value.dart'; + +class MorphIcon extends StatelessWidget { + const MorphIcon({ + super.key, + required this.morphFeature, + required this.morphTag, + }); + + final String morphFeature; + final String? morphTag; + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + + return CustomizedSvg( + svgUrl: getMorphSvgLink( + morphFeature: morphFeature, + morphTag: morphTag, + context: context, + ), + colorReplacements: theme.brightness == Brightness.dark + ? { + "white": theme.cardColor.hexValue.toString(), + "black": "white", + } + : {}, + errorIcon: Icon(getIconForMorphFeature(morphFeature)), + ); + } +} diff --git a/lib/pangea/morphs/morph_models.dart b/lib/pangea/morphs/morph_models.dart new file mode 100644 index 0000000000..05d57e9196 --- /dev/null +++ b/lib/pangea/morphs/morph_models.dart @@ -0,0 +1,95 @@ +import 'package:collection/collection.dart'; + +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; + +class MorphFeature { + final String feature; + final List tags; + + MorphFeature({required this.feature, required this.tags}); + + factory MorphFeature.fromJson(Map json) { + return MorphFeature( + feature: json['feature'], + tags: List.from(json['tag']), + ); + } + + List get displayTags => tags + .where( + (t) => + !["punct", "space", "sym", "x", "other"].contains(t.toLowerCase()), + ) + .toList(); + + Map toJson() { + return { + 'feature': feature, + 'tag': tags, + }; + } +} + +class MorphFeatuuresAndTags { + final String languageCode; + final List features; + + MorphFeatuuresAndTags({required this.languageCode, required this.features}); + + factory MorphFeatuuresAndTags.fromJson(Map json) { + return MorphFeatuuresAndTags( + languageCode: json['language_code'], + features: List.from( + json['features'].map((x) => MorphFeature.fromJson(x)), + ), + ); + } + + Map toJson() { + return { + 'language_code': languageCode, + 'features': features.map((x) => x.toJson()).toList(), + }; + } + + /// Returns the tags for a given feature + List getAllTags(String feature) => + features + .firstWhereOrNull((element) => element.feature == feature) + ?.tags ?? + []; + + /// Returns the display tags for a given feature + /// i.e. minus punc, space, x, etc + List getDisplayTags(String feature) => + features + .firstWhereOrNull((element) => element.feature == feature) + ?.displayTags ?? + []; + + List get displayFeatures => features + .where( + (f) => f.feature.toLowerCase() != "foreign", + ) + .toList(); + + List get categories => features.map((e) => e.feature).toList(); + + String guessMorphCategory(String morphLemma) { + for (final MorphFeature feature in features) { + if (feature.tags.contains(morphLemma)) { + // debugPrint( + // "found missing construct category for $morphLemma: $category", + // ); + return feature.feature; + } + } + ErrorHandler.logError( + m: "Morph construct lemma $morphLemma not found in morph categories and labels", + data: { + "morphLemma": morphLemma, + }, + ); + return "Other"; + } +} diff --git a/lib/pangea/morphs/morph_repo.dart b/lib/pangea/morphs/morph_repo.dart new file mode 100644 index 0000000000..c2ecbbe29a --- /dev/null +++ b/lib/pangea/morphs/morph_repo.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flutter/foundation.dart'; + +import 'package:get_storage/get_storage.dart'; +import 'package:http/http.dart'; + +import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/common/network/urls.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/morphs/default_morph_mapping.dart'; +import 'package:fluffychat/pangea/morphs/morph_models.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import '../common/network/requests.dart'; + +class _APICallCacheItem { + final DateTime time; + final Future future; + + _APICallCacheItem(this.time, this.future); +} + +class MorphsRepo { + // long-term storage of morphs + static final GetStorage _morphsStorage = GetStorage('morphs_storage'); + + // to avoid multiple fetches for the same language code + // by different parts of the app within a short time + static final shortTermCache = {}; + static const int _cacheDurationMinutes = 1; + + static void set(String languageCode, MorphFeatuuresAndTags response) { + _morphsStorage.write( + languageCode, + response.toJson(), + ); + } + + static MorphFeatuuresAndTags fromJson(Map json) { + return MorphFeatuuresAndTags.fromJson(json); + } + + static Future _fetch(String languageCode) async { + try { + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); + + final Response res = await req.get( + url: '${PApiUrls.morphFeaturesAndTags}/$languageCode', + ); + + final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); + final response = MorphsRepo.fromJson(decodedBody); + + set(languageCode, response); + + return response; + } catch (e, s) { + debugger(when: kDebugMode); + ErrorHandler.logError( + e: e, + s: s, + data: { + "languageCode": languageCode, + }, + ); + return defaultMorphMapping; + } + } + + /// this function fetches the morphs for a given language code + /// while remaining synchronous by using a default value + /// if the morphs are not yet fetched. we'll see if this works well + /// if not, we can make it async and update uses of this function + /// to be async as well + static MorphFeatuuresAndTags get([String? languageCode]) { + languageCode ??= + MatrixState.pangeaController.languageController.userL2?.langCode; + + if (languageCode == null) { + return defaultMorphMapping; + } + + // check if we have a cached morphs for this language code + final cachedJson = _morphsStorage.read(languageCode); + if (cachedJson != null) { + return MorphsRepo.fromJson(cachedJson); + } + + // check if we have a cached call for this language code + final _APICallCacheItem? cachedCall = shortTermCache[languageCode]; + if (cachedCall != null) { + if (DateTime.now().difference(cachedCall.time).inMinutes < + _cacheDurationMinutes) { + return defaultMorphMapping; + } else { + shortTermCache.remove(languageCode); + } + } + + // fetch the morphs but don't wait for it + final future = _fetch(languageCode); + shortTermCache[languageCode] = _APICallCacheItem(DateTime.now(), future); + + return defaultMorphMapping; + } +} diff --git a/lib/pangea/analytics/enums/parts_of_speech_enum.dart b/lib/pangea/morphs/parts_of_speech_enum.dart similarity index 100% rename from lib/pangea/analytics/enums/parts_of_speech_enum.dart rename to lib/pangea/morphs/parts_of_speech_enum.dart diff --git a/lib/pangea/spaces/widgets/download_analytics_dialog.dart b/lib/pangea/spaces/widgets/download_analytics_dialog.dart index b13067d82c..81a7983408 100644 --- a/lib/pangea/spaces/widgets/download_analytics_dialog.dart +++ b/lib/pangea/spaces/widgets/download_analytics_dialog.dart @@ -7,16 +7,16 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/analytics/enums/analytics_summary_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/analytics_summary_model.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_list_model.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/analytics_downloads/analytics_summary_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/analytics_summary_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_list_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/chat_settings/utils/download_file.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/widgets/matrix.dart'; class DownloadAnalyticsDialog extends StatefulWidget { diff --git a/lib/pangea/toolbar/enums/activity_type_enum.dart b/lib/pangea/toolbar/enums/activity_type_enum.dart index ec051fed82..d6bbfc8e7e 100644 --- a/lib/pangea/toolbar/enums/activity_type_enum.dart +++ b/lib/pangea/toolbar/enums/activity_type_enum.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; enum ActivityTypeEnum { wordMeaning, diff --git a/lib/pangea/toolbar/models/practice_activity_model.dart b/lib/pangea/toolbar/models/practice_activity_model.dart index 28d88893c7..2b034091d4 100644 --- a/lib/pangea/toolbar/models/practice_activity_model.dart +++ b/lib/pangea/toolbar/models/practice_activity_model.dart @@ -7,10 +7,10 @@ import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/morph_categories_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; +import 'package:fluffychat/pangea/morphs/morph_categories_enum.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_display_instructions_enum.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/multiple_choice_activity_model.dart'; diff --git a/lib/pangea/toolbar/models/practice_activity_record_model.dart b/lib/pangea/toolbar/models/practice_activity_record_model.dart index 83e1999eff..3fca7daf46 100644 --- a/lib/pangea/toolbar/models/practice_activity_record_model.dart +++ b/lib/pangea/toolbar/models/practice_activity_record_model.dart @@ -7,9 +7,9 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/practice_activity_model.dart'; diff --git a/lib/pangea/toolbar/repo/lemma_activity_generator.dart b/lib/pangea/toolbar/repo/lemma_activity_generator.dart index 6773a1a444..87e9eb3971 100644 --- a/lib/pangea/toolbar/repo/lemma_activity_generator.dart +++ b/lib/pangea/toolbar/repo/lemma_activity_generator.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/message_activity_request.dart'; diff --git a/lib/pangea/toolbar/repo/lemma_meaning_activity_generator.dart b/lib/pangea/toolbar/repo/lemma_meaning_activity_generator.dart index 9e3da8015b..8f371a2f0b 100644 --- a/lib/pangea/toolbar/repo/lemma_meaning_activity_generator.dart +++ b/lib/pangea/toolbar/repo/lemma_meaning_activity_generator.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_use_model.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_repo.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_request.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_response.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_repo.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/message_activity_request.dart'; import 'package:fluffychat/pangea/toolbar/models/multiple_choice_activity_model.dart'; diff --git a/lib/pangea/toolbar/repo/morph_activity_generator.dart b/lib/pangea/toolbar/repo/morph_activity_generator.dart index 415aa5de1a..56b79d95ae 100644 --- a/lib/pangea/toolbar/repo/morph_activity_generator.dart +++ b/lib/pangea/toolbar/repo/morph_activity_generator.dart @@ -2,11 +2,11 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/enums/morph_categories_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_identifier.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; +import 'package:fluffychat/pangea/morphs/morph_categories_enum.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/message_activity_request.dart'; import 'package:fluffychat/pangea/toolbar/models/multiple_choice_activity_model.dart'; diff --git a/lib/pangea/toolbar/widgets/message_selection_overlay.dart b/lib/pangea/toolbar/widgets/message_selection_overlay.dart index 88eb3d3897..6fde8f464d 100644 --- a/lib/pangea/toolbar/widgets/message_selection_overlay.dart +++ b/lib/pangea/toolbar/widgets/message_selection_overlay.dart @@ -7,7 +7,7 @@ import 'package:collection/collection.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/pages/chat/chat.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; diff --git a/lib/pangea/toolbar/widgets/message_token_text.dart b/lib/pangea/toolbar/widgets/message_token_text.dart index 49be95482d..fcb56cf102 100644 --- a/lib/pangea/toolbar/widgets/message_token_text.dart +++ b/lib/pangea/toolbar/widgets/message_token_text.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/events/utils/message_text_util.dart'; diff --git a/lib/pangea/toolbar/widgets/practice_activity/multiple_choice_activity.dart b/lib/pangea/toolbar/widgets/practice_activity/multiple_choice_activity.dart index d4f68159ca..63b20438d1 100644 --- a/lib/pangea/toolbar/widgets/practice_activity/multiple_choice_activity.dart +++ b/lib/pangea/toolbar/widgets/practice_activity/multiple_choice_activity.dart @@ -6,10 +6,10 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart'; import 'package:fluffychat/pangea/toolbar/enums/activity_type_enum.dart'; import 'package:fluffychat/pangea/toolbar/models/practice_activity_model.dart'; diff --git a/lib/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart index 4a3b9a1383..d1220b3419 100644 --- a/lib/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart @@ -6,11 +6,11 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/controllers/put_analytics_controller.dart'; -import 'package:fluffychat/pangea/analytics/enums/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics/models/constructs_model.dart'; -import 'package:fluffychat/pangea/analytics/widgets/gain_points.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; +import 'package:fluffychat/pangea/analytics_misc/gain_points_animation.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/choreographer/widgets/igc/card_error_widget.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; diff --git a/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart index f4faf4f46b..26abbb4874 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/lemma_meaning_widget.dart @@ -5,12 +5,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_repo.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_request.dart'; -import 'package:fluffychat/pangea/analytics/repo/lemma_info_response.dart'; -import 'package:fluffychat/pangea/analytics/widgets/text_loading_shimmer.dart'; +import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_repo.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_request.dart'; +import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LemmaMeaningWidget extends StatefulWidget { diff --git a/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart index 7702ee91d7..492dbc57dc 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/enums/lemma_category_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/construct_level_enum.dart'; import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; diff --git a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_center_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_center_widget.dart index 0b0483cd37..fcc909ec6e 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_center_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_center_widget.dart @@ -5,15 +5,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:fluffychat/pangea/analytics/constants/morph_categories_and_labels.dart'; -import 'package:fluffychat/pangea/analytics/enums/morph_categories_enum.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; import 'package:fluffychat/pangea/common/constants/model_keys.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/morphs/morph_categories_enum.dart'; +import 'package:fluffychat/pangea/morphs/morph_repo.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -140,12 +140,7 @@ class MorphologicalCenterWidgetState extends State { /// all morphological tags for the selected morphological category /// that are eligible for setting as the morphological tag List get allMorphTagsForEdit => - getLabelsForMorphCategory(widget.morphFeature) - .where( - (tag) => !["punct", "space", "sym", "x", "other"] - .contains(tag.toLowerCase()), - ) - .toList(); + MorphsRepo.get().getDisplayTags(widget.morphFeature); String get morphCopy => getMorphologicalCategoryCopy(widget.morphFeature, context) ?? diff --git a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_item.dart b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_item.dart index c90b09c73e..6faa827771 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_item.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_item.dart @@ -1,17 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/enums/morph_categories_enum.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_grammar_copy.dart'; -import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; +import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; +import 'package:fluffychat/pangea/morphs/morph_categories_enum.dart'; +import 'package:fluffychat/pangea/morphs/morph_icon.dart'; import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/word_zoom_activity_button.dart'; -import 'package:fluffychat/utils/color_value.dart'; class MorphologicalListItem extends StatelessWidget { final Function(String) onPressed; final String morphFeature; final String morphTag; - final IconData icon; - final String? svgLink; final bool isUnlocked; final bool isSelected; @@ -20,8 +17,6 @@ class MorphologicalListItem extends StatelessWidget { required this.onPressed, required this.morphFeature, required this.morphTag, - required this.icon, - this.svgLink, this.isUnlocked = true, this.isSelected = false, super.key, @@ -33,20 +28,7 @@ class MorphologicalListItem extends StatelessWidget { width: 40, height: 40, child: WordZoomActivityButton( - icon: svgLink != null - ? CustomizedSvg( - svgUrl: svgLink!, - colorReplacements: - Theme.of(context).brightness == Brightness.dark - ? { - "white": - Theme.of(context).cardColor.hexValue.toString(), - "black": "white", - } - : {}, - errorIcon: Icon(icon), - ) - : Icon(icon), + icon: MorphIcon(morphFeature: morphFeature, morphTag: morphTag), isSelected: isSelected, onPressed: () => onPressed(morphFeature), tooltip: isUnlocked diff --git a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_widget.dart index 54f443f3cf..8f809409af 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_widget.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/constants/morph_categories_and_labels.dart'; -import 'package:fluffychat/pangea/analytics/utils/get_svg_link.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/toolbar/widgets/word_zoom/morphs/morphological_list_item.dart'; @@ -76,12 +74,6 @@ class MorphologicalListWidget extends StatelessWidget { onPressed: setMorphFeature, morphFeature: morph.morphFeature, morphTag: morph.morphTag, - icon: getIconForMorphFeature(morph.morphFeature), - svgLink: getMorphSvgLink( - morphFeature: morph.morphFeature, - morphTag: morph.revealed ? morph.morphTag : null, - context: context, - ), isUnlocked: morph.revealed, isSelected: selectedMorphFeature == morph.morphFeature, ), diff --git a/lib/pangea/toolbar/widgets/word_zoom/word_zoom_center_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/word_zoom_center_widget.dart index 056375aa7f..767c422e7d 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/word_zoom_center_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/word_zoom_center_widget.dart @@ -3,7 +3,7 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/analytics/controllers/message_analytics_controller.dart'; +import 'package:fluffychat/pangea/analytics_misc/message_analytics_controller.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart';