From 6b643a841a31a2881b355c0230e501780c8e9b8f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 1 Nov 2024 13:59:23 -0400 Subject: [PATCH 01/13] make construct use category a String? instead of a list, set it to POS for vocab constructs --- .../controllers/my_analytics_controller.dart | 3 ++- .../models/analytics/constructs_model.dart | 20 ++++++++++++------ lib/pangea/models/lemma.dart | 18 ---------------- lib/pangea/models/pangea_token_model.dart | 21 ++++++++++++++++++- .../practice_activity_model.dart | 14 ++++++++++++- .../practice_activity_record_model.dart | 1 + .../models/representation_content_model.dart | 8 +++---- 7 files changed, 54 insertions(+), 31 deletions(-) diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 9c7523991..c4c9611c9 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -151,6 +151,7 @@ class MyAnalyticsController extends BaseController { form: token.lemma.form, constructType: ConstructTypeEnum.vocab, metadata: metadata, + category: token.pos, ), ) .toList(); @@ -161,7 +162,7 @@ class MyAnalyticsController extends BaseController { OneConstructUse( useType: useType, lemma: entry.value, - categories: [entry.key], + category: entry.key, constructType: ConstructTypeEnum.morph, metadata: metadata, ), diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index a9781f9ae..95a1ae101 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -74,7 +74,7 @@ class ConstructAnalyticsModel { class OneConstructUse { String? lemma; String? form; - List categories; + String? category; ConstructTypeEnum constructType; ConstructUseTypeEnum useType; @@ -89,7 +89,7 @@ class OneConstructUse { required this.lemma, required this.constructType, required this.metadata, - this.categories = const [], + this.category, this.form, this.id, }); @@ -104,13 +104,21 @@ class OneConstructUse { : null; debugger(when: kDebugMode && constructType == null); + final categoryEntry = json['categories']; + String? category; + if (categoryEntry != null) { + if ((categoryEntry is List) && categoryEntry.isNotEmpty) { + category = categoryEntry.first; + } else if (categoryEntry is String) { + category = categoryEntry; + } + } + return OneConstructUse( useType: ConstructUseTypeUtil.fromString(json['useType']), lemma: json['lemma'], form: json['form'], - categories: json['categories'] != null - ? List.from(json['categories']) - : [], + category: category, constructType: constructType ?? ConstructTypeEnum.vocab, id: json['id'], metadata: ConstructUseMetaData( @@ -134,7 +142,7 @@ class OneConstructUse { data['constructType'] = constructType.string; if (id != null) data['id'] = id; - data['categories'] = categories; + data['categories'] = category; return data; } diff --git a/lib/pangea/models/lemma.dart b/lib/pangea/models/lemma.dart index f297d60b0..1dc44c4b5 100644 --- a/lib/pangea/models/lemma.dart +++ b/lib/pangea/models/lemma.dart @@ -1,7 +1,3 @@ -import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; -import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; - /// Represents a lemma object class Lemma { /// [text] ex "ir" - text of the lemma of the word @@ -39,18 +35,4 @@ class Lemma { static Lemma create(String form) => Lemma(text: '', saveVocab: true, form: form); - - /// Given a [type] and [metadata], returns a [OneConstructUse] for this lemma - OneConstructUse toVocabUse( - ConstructUseTypeEnum type, - ConstructUseMetaData metadata, - ) { - return OneConstructUse( - useType: type, - lemma: text, - form: form, - constructType: ConstructTypeEnum.vocab, - metadata: metadata, - ); - } } diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 27361f272..bd47ed143 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -2,6 +2,8 @@ import 'dart:developer'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/message_activity_request.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:flutter/foundation.dart'; @@ -127,6 +129,7 @@ class PangeaToken { id: ConstructIdentifier( lemma: lemma.text, type: ConstructTypeEnum.vocab, + category: pos, ), ), ); @@ -135,8 +138,9 @@ class PangeaToken { constructs.add( ConstructWithXP( id: ConstructIdentifier( - lemma: morph.key, + lemma: morph.value, type: ConstructTypeEnum.morph, + category: morph.key, ), ), ); @@ -147,6 +151,21 @@ class PangeaToken { constructs: constructs, ); } + + /// Given a [type] and [metadata], returns a [OneConstructUse] for this lemma + OneConstructUse toVocabUse( + ConstructUseTypeEnum type, + ConstructUseMetaData metadata, + ) { + return OneConstructUse( + useType: type, + lemma: lemma.text, + form: lemma.form, + constructType: ConstructTypeEnum.vocab, + metadata: metadata, + category: pos, + ); + } } class PangeaTokenText { diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index 65f02c4f7..34ea62db0 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -12,16 +12,28 @@ import 'package:sentry_flutter/sentry_flutter.dart'; class ConstructIdentifier { final String lemma; final ConstructTypeEnum type; + String? category; - ConstructIdentifier({required this.lemma, required this.type}); + ConstructIdentifier({ + required this.lemma, + required this.type, + this.category, + }); factory ConstructIdentifier.fromJson(Map json) { + final categoryEntry = json['cat']; + String? category; + if (categoryEntry != null && categoryEntry is String) { + category = categoryEntry; + } + try { return ConstructIdentifier( lemma: json['lemma'] as String, type: ConstructTypeEnum.values.firstWhere( (e) => e.string == json['type'], ), + category: category, ); } catch (e, s) { debugger(when: kDebugMode); diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart index 2ece40b75..ffa6fd30b 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart @@ -146,6 +146,7 @@ class ActivityRecordResponse { constructType: construct.type, useType: useType, metadata: metadata, + category: construct.category, ), ) .toList(); diff --git a/lib/pangea/models/representation_content_model.dart b/lib/pangea/models/representation_content_model.dart index 9fb96f1e9..200f04ad1 100644 --- a/lib/pangea/models/representation_content_model.dart +++ b/lib/pangea/models/representation_content_model.dart @@ -157,7 +157,7 @@ class PangeaRepresentation { OneConstructUse( useType: useType, lemma: entry.value, - categories: [entry.key], + category: entry.key, constructType: ConstructTypeEnum.morph, metadata: metadata, ), @@ -166,7 +166,7 @@ class PangeaRepresentation { if (lemma.saveVocab) { uses.add( - lemma.toVocabUse( + token.toVocabUse( inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, metadata, ), @@ -213,7 +213,7 @@ class PangeaRepresentation { OneConstructUse( useType: ConstructUseTypeEnum.wa, lemma: entry.value, - categories: [entry.key], + category: entry.key, constructType: ConstructTypeEnum.morph, metadata: metadata, ), @@ -221,7 +221,7 @@ class PangeaRepresentation { } if (lemma.saveVocab) { uses.add( - lemma.toVocabUse( + token.toVocabUse( ConstructUseTypeEnum.wa, metadata, ), From da6d64972b60519a66464365aaa89b286d6a06a4 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 1 Nov 2024 15:19:52 -0400 Subject: [PATCH 02/13] add categories to analytics display --- .../analytics/construct_list_model.dart | 31 +++- .../models/analytics/constructs_model.dart | 4 + .../analytics_summary/analytics_popup.dart | 147 +++++++++++++----- 3 files changed, 138 insertions(+), 44 deletions(-) diff --git a/lib/pangea/models/analytics/construct_list_model.dart b/lib/pangea/models/analytics/construct_list_model.dart index 23763824c..747a54bb4 100644 --- a/lib/pangea/models/analytics/construct_list_model.dart +++ b/lib/pangea/models/analytics/construct_list_model.dart @@ -23,8 +23,8 @@ class ConstructListModel { List get uses => _uses.where((use) => use.constructType == type || type == null).toList(); - /// All unique lemmas used in the construct events - List get lemmas => constructList.map((e) => e.lemma).toSet().toList(); + // /// All unique lemmas used in the construct events + // List get lemmas => constructList.map((e) => e.lemma).toSet().toList(); /// All unique lemmas used in the construct events with non-zero points List get lemmasWithPoints => @@ -36,8 +36,13 @@ class ConstructListModel { final Map> lemmaToUses = {}; for (final use in uses) { if (use.lemma == null) continue; - lemmaToUses[use.lemma! + use.constructType.string] ??= []; - lemmaToUses[use.lemma! + use.constructType.string]!.add(use); + lemmaToUses[use.lemma! + + use.constructType.string + + (use.category ?? "Other")] ??= []; + lemmaToUses[use.lemma! + + use.constructType.string + + (use.category ?? "Other")]! + .add(use); } _constructMap = lemmaToUses.map( @@ -47,6 +52,7 @@ class ConstructListModel { uses: value, constructType: value.first.constructType, lemma: value.first.lemma!, + category: value.first.category, ), ), ); @@ -68,7 +74,7 @@ class ConstructListModel { _constructList = _constructMap!.values.toList(); _constructList!.sort((a, b) { - final comp = b.uses.length.compareTo(a.uses.length); + final comp = b.points.compareTo(a.points); if (comp != 0) return comp; return a.lemma.compareTo(b.lemma); }); @@ -79,6 +85,15 @@ class ConstructListModel { List get constructListWithPoints => constructList.where((constructUse) => constructUse.points > 0).toList(); + Map> get categoriesToUses { + final Map> categoriesMap = {}; + for (final use in constructListWithPoints) { + categoriesMap[use.category] ??= []; + categoriesMap[use.category]!.add(use); + } + return categoriesMap; + } + get maxXPPerLemma { return type != null ? type!.maxXPPerLemma @@ -141,12 +156,14 @@ class ConstructUses { final List uses; final ConstructTypeEnum constructType; final String lemma; + final String? _category; ConstructUses({ required this.uses, required this.constructType, required this.lemma, - }); + required category, + }) : _category = category; // Total points for all uses of this lemma int get points { @@ -165,6 +182,8 @@ class ConstructUses { }); return _lastUsed = lastUse; } + + String get category => _category ?? "Other"; } /// One lemma, a use type, and a list of uses diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 95a1ae101..85bd16d40 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -74,7 +74,11 @@ class ConstructAnalyticsModel { class OneConstructUse { String? lemma; String? form; + + /// For vocab constructs, this is the POS. For morph + /// constructs, this is the morphological category. String? category; + ConstructTypeEnum constructType; ConstructUseTypeEnum useType; diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart index d7978af73..ff29fc118 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -16,8 +16,76 @@ class AnalyticsPopup extends StatelessWidget { super.key, }); + List>> get categoriesToUses { + final entries = constructsModel.categoriesToUses.entries.toList(); + // Sort the list with custom logic + entries.sort((a, b) { + // Check if one of the keys is 'Other' + if (a.key == 'Other') return 1; + if (b.key == '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) { + Widget? dialogContent; + final bool hasNoData = constructsModel.constructListWithPoints.isEmpty; + final bool hasNoCategories = constructsModel.categoriesToUses.length == 1 && + constructsModel.categoriesToUses.keys.first == "Other"; + + if (hasNoData) { + dialogContent = Center(child: Text(L10n.of(context)!.noDataFound)); + } else if (hasNoCategories) { + dialogContent = ListView.builder( + itemCount: constructsModel.constructListWithPoints.length, + itemBuilder: (context, index) { + return ConstructUsesXPTile( + indicator: indicator, + constructsModel: constructsModel, + constructUses: constructsModel.constructListWithPoints[index], + ); + }, + ); + } else { + dialogContent = ListView.builder( + itemCount: categoriesToUses.length, + itemBuilder: (context, index) { + final category = categoriesToUses[index]; + return Column( + children: [ + ExpansionTile( + title: Text( + category.key != 'Other' + ? getGrammarCopy(category.key, context) + : category.key, + ), + children: category.value.map((constructUses) { + return ConstructUsesXPTile( + indicator: indicator, + constructsModel: constructsModel, + constructUses: constructUses, + ); + }).toList(), + ), + const Divider(height: 1), + ], + ); + }, + ); + } + return Dialog( child: ConstrainedBox( constraints: const BoxConstraints( @@ -36,44 +104,7 @@ class AnalyticsPopup extends StatelessWidget { ), body: Padding( padding: const EdgeInsets.symmetric(vertical: 20), - child: constructsModel.constructListWithPoints.isEmpty - ? Center( - child: Text(L10n.of(context)!.noDataFound), - ) - : ListView.builder( - itemCount: constructsModel.constructListWithPoints.length, - itemBuilder: (context, index) { - return Tooltip( - message: - "${constructsModel.constructListWithPoints[index].points} / ${constructsModel.maxXPPerLemma}", - child: ListTile( - onTap: () {}, - title: Text( - constructsModel.type == ConstructTypeEnum.morph - ? getGrammarCopy( - constructsModel - .constructListWithPoints[index].lemma, - context, - ) - : constructsModel - .constructListWithPoints[index].lemma, - ), - subtitle: LinearProgressIndicator( - value: constructsModel - .constructListWithPoints[index].points / - constructsModel.maxXPPerLemma, - minHeight: 20, - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: indicator.color(context), - ), - contentPadding: - const EdgeInsets.symmetric(horizontal: 20), - ), - ); - }, - ), + child: dialogContent, ), ), ), @@ -81,3 +112,43 @@ class AnalyticsPopup extends StatelessWidget { ); } } + +class ConstructUsesXPTile extends StatelessWidget { + final ProgressIndicatorEnum indicator; + final ConstructListModel constructsModel; + final ConstructUses constructUses; + + const ConstructUsesXPTile({ + required this.indicator, + required this.constructsModel, + required this.constructUses, + super.key, + }); + + @override + Widget build(BuildContext context) { + final lemma = constructUses.lemma; + return Tooltip( + message: "${constructUses.points} / ${constructsModel.maxXPPerLemma}", + child: ListTile( + onTap: () {}, + title: Text( + constructsModel.type == ConstructTypeEnum.morph + ? getGrammarCopy(lemma, context) + : lemma, + ), + subtitle: LinearProgressIndicator( + value: constructUses.points / constructsModel.maxXPPerLemma, + minHeight: 20, + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + color: indicator.color(context), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 20, + ), + ), + ); + } +} From 00cb1f1c75c9aab394ee5c095cebf9c9dcff2e8f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 1 Nov 2024 15:23:06 -0400 Subject: [PATCH 03/13] handling for 'cat' model key --- lib/pangea/models/analytics/constructs_model.dart | 2 +- .../practice_activity_model.dart | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 85bd16d40..e4e006952 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -108,7 +108,7 @@ class OneConstructUse { : null; debugger(when: kDebugMode && constructType == null); - final categoryEntry = json['categories']; + final categoryEntry = json['cat'] ?? json['categories']; String? category; if (categoryEntry != null) { if ((categoryEntry is List) && categoryEntry.isNotEmpty) { diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index 34ea62db0..ccdd3802a 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -21,10 +21,14 @@ class ConstructIdentifier { }); factory ConstructIdentifier.fromJson(Map json) { - final categoryEntry = json['cat']; + final categoryEntry = json['cat'] ?? json['categories']; String? category; - if (categoryEntry != null && categoryEntry is String) { - category = categoryEntry; + if (categoryEntry != null) { + if (categoryEntry is String) { + category = categoryEntry; + } else if (categoryEntry is List) { + category = categoryEntry.first; + } } try { @@ -46,6 +50,7 @@ class ConstructIdentifier { return { 'lemma': lemma, 'type': type.string, + 'cat': category, }; } From f989d3b466e23455fa4e4a9f77c2124581393ff6 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Fri, 1 Nov 2024 17:21:16 -0400 Subject: [PATCH 04/13] update getGrammarCopy to use category, updated grammar copy --- assets/l10n/intl_en.arb | 402 ++++++++++------ lib/pangea/utils/get_grammar_copy.dart | 637 +++++++++++++++---------- 2 files changed, 662 insertions(+), 377 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 1731cadf2..e896b9791 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4219,143 +4219,273 @@ "openVoiceSettings": "Click here to open voice settings", "playAudio": "Play", "stop": "Stop", - "grammarCopySCONJ": "Subordinating Conjunction", - "grammarCopyNUM": "Number", - "grammarCopyVERB": "Verb", - "grammarCopyAFFIX": "Affix", - "grammarCopyPARTpos": "Particle", - "grammarCopyADJ": "Adjective", - "grammarCopyCCONJ": "Coordinating Conjunction", - "grammarCopyPUNCT": "Punctuation", - "grammarCopyADV": "Adverb", - "grammarCopyAUX": "Auxiliary", - "grammarCopySPACE": "Space", - "grammarCopySYM": "Symbol", - "grammarCopyDET": "Determiner", - "grammarCopyPRON": "Pronoun", - "grammarCopyADP": "Adposition", - "grammarCopyPROPN": "Proper Noun", - "grammarCopyNOUN": "Noun", - "grammarCopyINTJ": "Interjection", - "grammarCopyX": "Other", - "grammarCopyFem": "Feminine", - "grammarCopy2": "Second Person", - "grammarCopyImp": "Imperative", - "grammarCopyQest": "Question", - "grammarCopyPerf": "Perfect", - "grammarCopyAccNom": "Accusative, Nominative", - "grammarCopyObl": "Oblique Case", - "grammarCopyAct": "Active", - "grammarCopyBrck": "Bracket", - "grammarCopyArt": "Article", - "grammarCopySing": "Singular", - "grammarCopyMasc": "Masculine", - "grammarCopyMod": "Modal", - "grammarCopyAdverbial": "Adverbial", - "grammarCopyPeri": "Periphrastic", - "grammarCopyDigit": "Digit", - "grammarCopyNot_proper": "Not Proper", - "grammarCopyCard": "Cardinal", - "grammarCopyProp": "Proper", - "grammarCopyDash": "Dash", - "grammarCopyYes": "Yes", - "grammarCopySemi": "Semicolon", - "grammarCopyComm": "Comma", - "grammarCopyCnd": "Conditional", - "grammarCopyIntRel": "Interrogative, Relative", - "grammarCopyAcc": "Accusative", - "grammarCopyPartTag": "Partitive", - "grammarCopyInt": "Interrogative", - "grammarCopyPast": "Past", - "grammarCopySup": "Superlative", - "grammarCopyColo": "Colon", - "grammarCopy3": "Third Person", - "grammarCopyPlur": "Plural", - "grammarCopyNpr": "Proper Noun", - "grammarCopyInterrogative": "Interrogative", - "grammarCopyInfm": "Informal", - "grammarCopyTim": "Time", - "grammarCopyNeg": "Negative", - "grammarCopyTot": "Total", - "grammarCopyAdnomial": "Adnominal", - "grammarCopyProg": "Progressive", - "grammarCopySub": "Subjunctive", - "grammarCopyComplementive": "Complementive", - "grammarCopyNom": "Nominative", - "grammarCopyFut": "Future", - "grammarCopyDat": "Dative", - "grammarCopyPres": "Present", - "grammarCopyNeut": "Neuter", - "grammarCopyRel": "Relative", - "grammarCopyFinal_ending": "Final Ending", - "grammarCopyDem": "Demonstrative", - "grammarCopyPre": "Preposition", - "grammarCopyFin": "Finite", - "grammarCopyPos": "Positive", - "grammarCopyQuot": "Quotation", - "grammarCopyGer": "Gerund", - "grammarCopyPass": "Passive", - "grammarCopyGen": "Genitive", - "grammarCopyPrs": "Present", - "grammarCopyDef": "Definite", - "grammarCopyOrd": "Ordinal", - "grammarCopyIns": "Instrumental", - "grammarCopyAccDat": "Accusative, Dative", - "grammarCopyInf": "Infinitive", - "grammarCopyLong": "Long", - "grammarCopyLoc": "Locative", - "grammarCopyInd": "Indicative", - "grammarCopyCmp": "Comparative", - "grammarCopyRelative_case": "Relative Case", - "grammarCopyExcl": "Exclamative", - "grammarCopy1": "First Person", - "grammarCopyIni": "Initial", - "grammarCopyPerson": "Person", - "grammarCopyForeign": "Foreign", - "grammarCopyVoice": "Voice", - "grammarCopyVerbType": "Verb Type", - "grammarCopyPoss": "Possessive", - "grammarCopyPrepCase": "Prepositional Case", - "grammarCopyNumType": "Numeral Type", - "grammarCopyNounType": "Noun Type", - "grammarCopyReflex": "Reflexive", - "grammarCopyPronType": "Pronoun Type", - "grammarCopyPunctSide": "Punctuation Side", - "grammarCopyVerbForm": "Verb Form", - "grammarCopyGender": "Gender", - "grammarCopyMood": "Mood", - "grammarCopyAspect": "Aspect", - "grammarCopyPunctType": "Punctuation Type", - "grammarCopyTense": "Tense", - "grammarCopyDegree": "Degree", - "grammarCopyPolite": "Politeness", - "grammarCopyAdvType": "Adverb Type", - "grammarCopyNumber": "Number", - "grammarCopyConjType": "Conjunction Type", - "grammarCopyPolarity": "Polarity", - "grammarCopyNumberPsor": "Possessor's Number", - "grammarCopyCase": "Case", - "grammarCopyDefinite": "Definiteness", - "grammarCopyNumForm": "Numeral Form", - "grammarCopyAdn": "Adnominal", - "grammarCopyVoc": "Vocative", - "grammarCopyCmpl": "Complementizer", - "grammarCopyAdv": "Adverbial", - "grammarCopyUnknown": "Unknown", - "grammarCopyJus": "Jussive", - "grammarCopyCom": "Common", - "grammarCopyCaus": "Causative", - "grammarCopyAux": "Auxiliary", - "grammarCopyRflx": "Reflexive", - "grammarCopyPar": "Partitive", - "grammarCopySpc": "Specific", - "grammarCopyPqp": "Pluperfect", - "grammarCopyRef": "Reflexive Case", - "grammarCopyShrt": "Short", - "grammarCopyDual": "Dual", - "grammarCopyLng": "Long", - "grammarCopyMid": "Middle Voice", + "grammarCopyPOSsconj": "Subordinating Conjunction", + "grammarCopyPOSnum": "Number", + "grammarCopyPOSverb": "Verb", + "grammarCopyPOSaffix": "Affix", + "grammarCopyPOSpart": "Particle", + "grammarCopyPOSadj": "Adjective", + "grammarCopyPOScconj": "Coordinating Conjunction", + "grammarCopyPOSpunct": "Punctuation", + "grammarCopyPOSadv": "Adverb", + "grammarCopyPOSaux": "Auxiliary", + "grammarCopyPOSspace": "Space", + "grammarCopyPOSsym": "Symbol", + "grammarCopyPOSdet": "Determiner", + "grammarCopyPOSpron": "Pronoun", + "grammarCopyPOSadp": "Adposition", + "grammarCopyPOSpropn": "Proper Noun", + "grammarCopyPOSnoun": "Noun", + "grammarCopyPOSintj": "Interjection", + "grammarCopyPOSx": "Other", + "grammarCopyGENDERfem": "Feminine", + "grammarCopyPERSON2": "Second Person", + "grammarCopyMOODimp": "Imperative", + "grammarCopyPUNCTTYPEqest": "Question", + "grammarCopyASPECTperf": "Perfect", + "grammarCopyCASEaccnom": "Accusative, Nominative", + "grammarCopyCASEobl": "Oblique Case", + "grammarCopyVOICEact": "Active", + "grammarCopyPUNCTTYPEbrck": "Bracket", + "grammarCopyNOUNTYPEart": "Article", + "grammarCopyNUMBERsing": "Singular", + "grammarCopyGENDERmasc": "Masculine", + "grammarCopyVERBTYPEmod": "Modal", + "grammarCopyADVTYPEadverbial": "Adverbial", + "grammarCopyTENSEperi": "Periphrastic", + "grammarCopyNUMFORMdigit": "Digit", + "grammarCopyNOUNTYPEnot_proper": "Not Proper", + "grammarCopyNUMTYPEcard": "Cardinal", + "grammarCopyNOUNTYPEprop": "Proper", + "grammarCopyPUNCTTYPEdash": "Dash", + "grammarCopyPUNCTTYPEyes": "Yes", + "grammarCopyPUNCTTYPEsemi": "Semicolon", + "grammarCopyPUNCTTYPEcomm": "Comma", + "grammarCopyMOODcnd": "Conditional", + "grammarCopyCASEacc": "Accusative", + "grammarCopyPARTTYPEpart": "Partitive", + "grammarCopyTENSEpast": "Past", + "grammarCopyDEGREEsup": "Superlative", + "grammarCopyPUNCTTYPEcolo": "Colon", + "grammarCopyPERSON3": "Third Person", + "grammarCopyNUMBERplur": "Plural", + "grammarCopyPRONTYPEnpr": "Proper Noun", + "grammarCopyPRONTYPEinterrogative": "Interrogative", + "grammarCopyPOLITEinfm": "Informal", + "grammarCopyADVTYPEtim": "Time", + "grammarCopyPOLARITYneg": "Negative", + "grammarCopyNUMTYPEtot": "Total", + "grammarCopyADVTYPEadnomial": "Adnominal", + "grammarCopyASPECTprog": "Progressive", + "grammarCopyMOODsub": "Subjunctive", + "grammarCopyVERBFORMcomplementive": "Complementive", + "grammarCopyCASEnom": "Nominative", + "grammarCopyTENSEfut": "Future", + "grammarCopyCASEdat": "Dative", + "grammarCopyTENSEpres": "Present", + "grammarCopyGENDERneut": "Neuter", + "grammarCopyPRONTYPErel": "Relative", + "grammarCopyVERBFORMfinalEnding": "Final Ending", + "grammarCopyPRONTYPEdem": "Demonstrative", + "grammarCopyPREPCASEpre": "Preposition", + "grammarCopyVERBFORMfin": "Finite", + "grammarCopyDEGREEpos": "Positive", + "grammarCopyPUNCTTYPEquot": "Quotation", + "grammarCopyVERBFORMger": "Gerund", + "grammarCopyVOICEpass": "Passive", + "grammarCopyCASEgen": "Genitive", + "grammarCopyTENSEprs": "Present", + "grammarCopyDEFINITEdef": "Definite", + "grammarCopyNUMTYPEord": "Ordinal", + "grammarCopyCASEins": "Instrumental", + "grammarCopyVERBFORMinf": "Infinitive", + "grammarCopyNUMFORMlong": "Long", + "grammarCopyCASEloc": "Locative", + "grammarCopyMOODind": "Indicative", + "grammarCopyDEGREEcmp": "Comparative", + "grammarCopyCASErelativeCase": "Relative Case", + "grammarCopyPUNCTTYPEexcl": "Exclamative", + "grammarCopyPERSON1": "First Person", + "grammarCopyPUNCTSIDEini": "Initial", + "grammarCopyGENDERperson": "Person", + "grammarCopyFOREIGNyes": "Foreign", + "grammarCopyVOICEvoice": "Voice", + "grammarCopyVERBTYPEverbType": "Verb Type", + "grammarCopyPOSSpass": "Possessive", + "grammarCopyPREPCASEprepCase": "Prepositional Case", + "grammarCopyNUMTYPEnumType": "Numeral Type", + "grammarCopyNOUNTYPEnounType": "Noun Type", + "grammarCopyREFLEXreflex": "Reflexive", + "grammarCopyPRONTYPEpronType": "Pronoun Type", + "grammarCopyPUNCTSIDEpunctSide": "Punctuation Side", + "grammarCopyVERBFORMverbForm": "Verb Form", + "grammarCopyGENDERgender": "Gender", + "grammarCopyMOODmood": "Mood", + "grammarCopyASPECTaspect": "Aspect", + "grammarCopyPUNCTTYPEpunctType": "Punctuation Type", + "grammarCopyTENSEtense": "Tense", + "grammarCopyDEGREEdegree": "Degree", + "grammarCopyPOLITEpolite": "Politeness", + "grammarCopyADVTYPEadvType": "Adverb Type", + "grammarCopyNUMFORMnumber": "Number", + "grammarCopyCONJTYPEconjType": "Conjunction Type", + "grammarCopyPOLARITYpolarity": "Polarity", + "grammarCopyCASEcase": "Case", + "grammarCopyDEFINITEdefinite": "Definiteness", + "grammarCopyNUMFORMnumForm": "Numeral Form", + "grammarCopyPRONTYPEadn": "Adnominal", + "grammarCopyVOCvoc": "Vocative", + "grammarCopyCMPLcmpl": "Complementizer", + "grammarCopyADVadv": "Adverbial", + "grammarCopyMOODjus": "Jussive", + "grammarCopyGENDERcom": "Common", + "grammarCopyREFLEXrflx": "Reflexive", + "grammarCopyPARTTYPEpar": "Partitive", + "grammarCopySPCspc": "Specific", + "grammarCopyTENSEpqp": "Pluperfect", + "grammarCopyREFLEXref": "Reflexive Case", + "grammarCopyPUNCTTYPEnshrt": "Short", + "grammarCopyNUMBERdual": "Dual", + "grammarCopyNUMFORMlng": "Long", + "grammarCopyVOICEmid": "Middle Voice", + "grammarCopyINTRELintRel": "Interrogative, Relative", + "grammarCopyINTint": "Interrogative", + "grammarCopyVOICEcaus": "Causative Voice", "grammarCopyUnknown": "Unknown", + "grammarCopyEVIDENTevident": "Evidentiality", + "grammarCopyNUMFORMnumberPsor": "Possessor's Number", + "grammarCopyASPECThab": "Habitual", + "grammarCopyCASEabl": "Ablative Case", + "grammarCopyCASEall": "Allative Case", + "grammarCopyCASEess": "Essive Case", + "grammarCopyCASEtra": "Translative Case", + "grammarCopyCASEequ": "Equative Case", + "grammarCopyCASEdis": "Distributive Case", + "grammarCopyCASEabs": "Absolutive Case", + "grammarCopyCASEerg": "Ergative Case", + "grammarCopyCASEcau": "Causal Case", + "grammarCopyCASEben": "Benefactive Case", + "grammarCopyCASEtem": "Temporal Case", + "grammarCopyCONJTYPEcoord": "Coordinating Conjunction", + "grammarCopyDEFINITEcons": "Construct State", + "grammarCopyDEGREEabs": "Absolute Degree", + "grammarCopyEVIDENTfh": "Factual Evidentiality", + "grammarCopyEVIDENTnfh": "Non-factual Evidentiality", + "grammarCopyMOODopt": "Optative Mood", + "grammarCopyMOODadm": "Admirative Mood", + "grammarCopyMOODdes": "Desiderative Mood", + "grammarCopyMOODnec": "Necessitative Mood", + "grammarCopyMOODpot": "Potential Mood", + "grammarCopyMOODprp": "Propositive Mood", + "grammarCopyMOODqot": "Quotative Mood", + "grammarCopyNUMFORMword": "Word Form", + "grammarCopyNUMFORMroman": "Roman Numeral", + "grammarCopyNUMFORMletter": "Letter Form", + "grammarCopyNUMTYPEmult": "Multiplicative Numeral", + "grammarCopyNUMTYPEfrac": "Fractional Numeral", + "grammarCopyNUMTYPEsets": "Set Numeral", + "grammarCopyNUMTYPErange": "Range Numeral", + "grammarCopyNUMTYPEdist": "Distributive Numeral", + "grammarCopyNUMBERtri": "Trial Number", + "grammarCopyNUMBERpauc": "Paucal Number", + "grammarCopyNUMBERgrpa": "Greater Paucal Number", + "grammarCopyNUMBERgrpl": "Greater Plural Number", + "grammarCopyNUMBERinv": "Inverse Number", + "grammarCopyPERSON0": "Zero Person", + "grammarCopyPERSON4": "Fourth Person", + "grammarCopyPOLITEform": "Formal Politeness", + "grammarCopyPOLITEelev": "Elevated Politeness", + "grammarCopyPOLITEhumb": "Humble Politeness", + "grammarCopyPRONTYPEemp": "Emphatic Pronoun", + "grammarCopyPRONTYPEexc": "Exclamative Pronoun", + "grammarCopyPRONTYPErcp": "Reciprocal Pronoun", + "grammarCopyPRONTYPEintRelPronType": "Interrogative-Relative Pronoun", + "grammarCopyTENSEaor": "Aorist Tense", + "grammarCopyTENSEeps": "Epistemic Tense", + "grammarCopyTENSEprosp": "Prospective Tense", + "grammarCopyVERBFORMpart": "Participle Form", + "grammarCopyVERBFORMconv": "Converb Form", + "grammarCopyVERBFORMvnoun": "Verbal Noun", + "grammarCopyVOICEantip": "Antipassive Voice", + "grammarCopyVOICEcauVoice": "Causative Voice", + "grammarCopyVOICedir": "Direct Voice", + "grammarCopyVOICEinvVoice": "Inverse Voice", + "grammarCopyVOICErcpVoice": "Reciprocal Voice", + "grammarCopyPOS": "Part of Speech", + "grammarCopyGENDER": "Gender", + "grammarCopyPERSON": "Person", + "grammarCopyMOOD": "Mood", + "grammarCopyPUNCTTYPE": "Punctuation Type", + "grammarCopyASPECT": "Aspect", + "grammarCopyCASE": "Case", + "grammarCopyVOICE": "Voice", + "grammarCopyNOUNTYPE": "Noun Type", + "grammarCopyVERBTYPE": "Verb Type", + "grammarCopyADVTYPE": "Adverb Type", + "grammarCopyNUMFORM": "Numeral Form", + "grammarCopyNUMTYPE": "Numeral Type", + "grammarCopyNUMBER": "Number", + "grammarCopyDEFINITE": "Definiteness", + "grammarCopyDEGREE": "Degree", + "grammarCopyEVIDENT": "Evidentiality", + "grammarCopyFOREIGN": "Foreign", + "grammarCopyPOLARITY": "Polarity", + "grammarCopyPOLITE": "Politeness", + "grammarCopyPREPCASE": "Prepositional Case", + "grammarCopyPRONTYPE": "Pronoun Type", + "grammarCopyPUNCTSIDE": "Punctuation Side", + "grammarCopyREFLEX": "Reflexive", + "grammarCopyTENSE": "Tense", + "grammarCopyVERBFORM": "Verb Form", + "grammarCopyCONJTYPE": "Conjunction Type", + "grammarCopySPC": "Specificity", + "grammarCopyPARTTYPE": "Partitive Type", + "grammarCopyINTREL": "Interrogative-Relative", + "grammarCopyNUMFORMpsor": "Possessor's Number", + "grammarCopyUNKNOWN": "Unknown", + "grammarCopyNUMBERPSOR": "Possessor's Number", + "grammarCopyPOSS": "Possessive", + "grammarCopyASPECTimp": "Imperfective Aspect", + "grammarCopyCASEvoc": "Vocative Case", + "grammarCopyCASEcom": "Comitative Case", + "grammarCopyCASEpar": "Partitive Case", + "grammarCopyCASEadv": "Adverbial Case", + "grammarCopyCASEref": "Referential Case", + "grammarCopyCASErel": "Relative Case", + "grammarCopyCASEsub": "Subessive Case", + "grammarCopyCASEsup": "Superessive Case", + "grammarCopyCASEaccdat": "Accusative-Dative Case", + "grammarCopyCASEpre": "Prepositional Case", + "grammarCopyCONJTYPEsub": "Subordinating Conjunction", + "grammarCopyCONJTYPEcmp": "Comparative Conjunction", + "grammarCopyDEFINITEind": "Indefinite", + "grammarCopyMOODint": "Interrogative Mood", + "grammarCopyNOUNTYPEcomm": "Common Noun", + "grammarCopyNUMBERPSORsing": "Possessor's Singular", + "grammarCopyNUMBERPSORplur": "Possessor's Plural", + "grammarCopyNUMBERPSORdual": "Possessor's Dual", + "grammarCopyPOLARITYpos": "Positive Polarity", + "grammarCopyPOSSyes": "Possessive", + "grammarCopyPREPCASEnpr": "Non-prepositional", + "grammarCopyPRONTYPEprs": "Personal Pronoun", + "grammarCopyPRONTYPEint": "Interrogative Pronoun", + "grammarCopyPRONTYPEtot": "Total Pronoun", + "grammarCopyPRONTYPEneg": "Negative Pronoun", + "grammarCopyPRONTYPEart": "Article Pronoun", + "grammarCopyPRONTYPEind": "Indefinite Pronoun", + "grammarCopyPRONTYPEintrel": "Interrogative-Relative Pronoun", + "grammarCopyPUNCTSIDEfin": "Final Punctuation", + "grammarCopyPUNCTTYPEperi": "Period", + "grammarCopyREFLEXyes": "Reflexive", + "grammarCopyTENSEimp": "Imperfect Tense", + "grammarCopyVERBFORMsup": "Supine Form", + "grammarCopyVERBFORMadn": "Adnominal Form", + "grammarCopyVERBFORMlng": "Long Form", + "grammarCopyVERBTYPEcaus": "Causative Verb", + "grammarCopyVOICEcau": "Causative Voice", + "grammarCopyVOICEdir": "Direct Voice", + "grammarCopyVOICEinv": "Inverse Voice", + "grammarCopyVOICErcp": "Reciprocal Voice", "enterPrompt": "Please enter a system prompt", "selectBotLanguage": "Select bot language", "chooseVoice": "Choose a voice", diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index 31a907c36..3e89bd65a 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -5,243 +5,398 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -String getGrammarCopy(String tag, BuildContext context) { - switch (tag) { - case 'SCONJ': - return L10n.of(context)!.grammarCopySCONJ; - case 'NUM': - return L10n.of(context)!.grammarCopyNUM; - case 'VERB': - return L10n.of(context)!.grammarCopyVERB; - case 'AFFIX': - return L10n.of(context)!.grammarCopyAFFIX; - case 'PART': - return L10n.of(context)!.grammarCopyPARTpos; - case 'ADJ': - return L10n.of(context)!.grammarCopyADJ; - case 'CCONJ': - return L10n.of(context)!.grammarCopyCCONJ; - case 'PUNCT': - return L10n.of(context)!.grammarCopyPUNCT; - case 'ADV': - return L10n.of(context)!.grammarCopyADV; - case 'AUX': - return L10n.of(context)!.grammarCopyAUX; - case 'SPACE': - return L10n.of(context)!.grammarCopySPACE; - case 'SYM': - return L10n.of(context)!.grammarCopySYM; - case 'DET': - return L10n.of(context)!.grammarCopyDET; - case 'PRON': - return L10n.of(context)!.grammarCopyPRON; - case 'ADP': - return L10n.of(context)!.grammarCopyADP; - case 'PROPN': - return L10n.of(context)!.grammarCopyPROPN; - case 'NOUN': - return L10n.of(context)!.grammarCopyNOUN; - case 'INTJ': - return L10n.of(context)!.grammarCopyINTJ; - case 'X': - return L10n.of(context)!.grammarCopyX; - case 'Fem': - return L10n.of(context)!.grammarCopyFem; - case '2': - return L10n.of(context)!.grammarCopy2; - case 'Imp': - return L10n.of(context)!.grammarCopyImp; - case 'Qest': - return L10n.of(context)!.grammarCopyQest; - case 'Perf': - return L10n.of(context)!.grammarCopyPerf; - case 'Acc,Nom': - return L10n.of(context)!.grammarCopyAccNom; - case 'Obl': - return L10n.of(context)!.grammarCopyObl; - case 'Act': - return L10n.of(context)!.grammarCopyAct; - case 'Brck': - return L10n.of(context)!.grammarCopyBrck; - case 'Art': - return L10n.of(context)!.grammarCopyArt; - case 'Sing': - return L10n.of(context)!.grammarCopySing; - case 'Masc': - return L10n.of(context)!.grammarCopyMasc; - case 'Mod': - return L10n.of(context)!.grammarCopyMod; - case 'Adverbial': - return L10n.of(context)!.grammarCopyAdverbial; - case 'Peri': - return L10n.of(context)!.grammarCopyPeri; - case 'Digit': - return L10n.of(context)!.grammarCopyDigit; - case 'Not_proper': - return L10n.of(context)!.grammarCopyNot_proper; - case 'Card': - return L10n.of(context)!.grammarCopyCard; - case 'Prop': - return L10n.of(context)!.grammarCopyProp; - case 'Dash': - return L10n.of(context)!.grammarCopyDash; - case 'Yes': - return L10n.of(context)!.grammarCopyYes; - case 'Semi': - return L10n.of(context)!.grammarCopySemi; - case 'Comm': - return L10n.of(context)!.grammarCopyComm; - case 'Cnd': - return L10n.of(context)!.grammarCopyCnd; - case 'Int,Rel': - return L10n.of(context)!.grammarCopyIntRel; - case 'Acc': - return L10n.of(context)!.grammarCopyAcc; - case 'Part': - return L10n.of(context)! - .grammarCopyPartTag; // To avoid conflict with 'PART' POS - case 'Int': - return L10n.of(context)!.grammarCopyInt; - case 'Past': - return L10n.of(context)!.grammarCopyPast; - case 'Sup': - return L10n.of(context)!.grammarCopySup; - case 'Colo': - return L10n.of(context)!.grammarCopyColo; - case '3': - return L10n.of(context)!.grammarCopy3; - case 'Plur': - return L10n.of(context)!.grammarCopyPlur; - case 'Npr': - return L10n.of(context)!.grammarCopyNpr; - case 'Interrogative': - return L10n.of(context)!.grammarCopyInterrogative; - case 'Infm': - return L10n.of(context)!.grammarCopyInfm; - case 'Tim': - return L10n.of(context)!.grammarCopyTim; - case 'Neg': - return L10n.of(context)!.grammarCopyNeg; - case 'Tot': - return L10n.of(context)!.grammarCopyTot; - case 'Adnomial': - return L10n.of(context)!.grammarCopyAdnomial; - case 'Prog': - return L10n.of(context)!.grammarCopyProg; - case 'Sub': - return L10n.of(context)!.grammarCopySub; - case 'Complementive': - return L10n.of(context)!.grammarCopyComplementive; - case 'Nom': - return L10n.of(context)!.grammarCopyNom; - case 'Fut': - return L10n.of(context)!.grammarCopyFut; - case 'Dat': - return L10n.of(context)!.grammarCopyDat; - case 'Pres': - return L10n.of(context)!.grammarCopyPres; - case 'Neut': - return L10n.of(context)!.grammarCopyNeut; - case 'Rel': - return L10n.of(context)!.grammarCopyRel; - case 'Final_ending': - return L10n.of(context)!.grammarCopyFinal_ending; - case 'Dem': - return L10n.of(context)!.grammarCopyDem; - case 'Pre': - return L10n.of(context)!.grammarCopyPre; - case 'Fin': - return L10n.of(context)!.grammarCopyFin; - case 'Pos': - return L10n.of(context)!.grammarCopyPos; - case 'Quot': - return L10n.of(context)!.grammarCopyQuot; - case 'Ger': - return L10n.of(context)!.grammarCopyGer; - case 'Pass': - return L10n.of(context)!.grammarCopyPass; - case 'Gen': - return L10n.of(context)!.grammarCopyGen; - case 'Prs': - return L10n.of(context)!.grammarCopyPrs; - case 'Def': - return L10n.of(context)!.grammarCopyDef; - case 'Ord': - return L10n.of(context)!.grammarCopyOrd; - case 'Ins': - return L10n.of(context)!.grammarCopyIns; - case 'Acc,Dat': - return L10n.of(context)!.grammarCopyAccDat; - case 'Inf': - return L10n.of(context)!.grammarCopyInf; - case 'Long': - return L10n.of(context)!.grammarCopyLong; - case 'Ind': - return L10n.of(context)!.grammarCopyInd; - case 'Cmp': - return L10n.of(context)!.grammarCopyCmp; - case 'Relative_case': - return L10n.of(context)!.grammarCopyRelative_case; - case 'Excl': - return L10n.of(context)!.grammarCopyExcl; - case '1': - return L10n.of(context)!.grammarCopy1; - case 'Ini': - return L10n.of(context)!.grammarCopyIni; - case 'Person': - return L10n.of(context)!.grammarCopyPerson; - case 'Foreign': - return L10n.of(context)!.grammarCopyForeign; - case 'Voice': - return L10n.of(context)!.grammarCopyVoice; - case 'VerbType': - return L10n.of(context)!.grammarCopyVerbType; - case 'Poss': - return L10n.of(context)!.grammarCopyPoss; - case 'PrepCase': - return L10n.of(context)!.grammarCopyPrepCase; - case 'NumType': - return L10n.of(context)!.grammarCopyNumType; - case 'NounType': - return L10n.of(context)!.grammarCopyNounType; - case 'Reflex': - return L10n.of(context)!.grammarCopyReflex; - case 'PronType': - return L10n.of(context)!.grammarCopyPronType; - case 'PunctSide': - return L10n.of(context)!.grammarCopyPunctSide; - case 'VerbForm': - return L10n.of(context)!.grammarCopyVerbForm; - case 'Gender': - return L10n.of(context)!.grammarCopyGender; - case 'Mood': - return L10n.of(context)!.grammarCopyMood; - case 'Aspect': - return L10n.of(context)!.grammarCopyAspect; - case 'PunctType': - return L10n.of(context)!.grammarCopyPunctType; - case 'Tense': - return L10n.of(context)!.grammarCopyTense; - case 'Degree': - return L10n.of(context)!.grammarCopyDegree; - case 'Polite': - return L10n.of(context)!.grammarCopyPolite; - case 'AdvType': - return L10n.of(context)!.grammarCopyAdvType; - case 'Number': - return L10n.of(context)!.grammarCopyNumber; - case 'ConjType': - return L10n.of(context)!.grammarCopyConjType; - case 'Polarity': - return L10n.of(context)!.grammarCopyPolarity; - case 'Number[psor]': - return L10n.of(context)!.grammarCopyNumberPsor; - case 'Case': - return L10n.of(context)!.grammarCopyCase; - case 'Definite': - return L10n.of(context)!.grammarCopyDefinite; - case 'NumForm': - return L10n.of(context)!.grammarCopyNumForm; +String getGrammarCopy( + {required String category, + required String feature, + required BuildContext context}) { + final String key = + 'grammarCopy${category.toUpperCase()}${feature.toLowerCase()}'; + + switch (key) { + case 'grammarCopyPOSsconj': + return L10n.of(context)!.grammarCopyPOSsconj; + case 'grammarCopyPOSnum': + return L10n.of(context)!.grammarCopyPOSnum; + case 'grammarCopyPOSverb': + return L10n.of(context)!.grammarCopyPOSverb; + case 'grammarCopyPOSaffix': + return L10n.of(context)!.grammarCopyPOSaffix; + case 'grammarCopyPOSpart': + return L10n.of(context)!.grammarCopyPOSpart; + case 'grammarCopyPOSadj': + return L10n.of(context)!.grammarCopyPOSadj; + case 'grammarCopyPOScconj': + return L10n.of(context)!.grammarCopyPOScconj; + case 'grammarCopyPOSpunct': + return L10n.of(context)!.grammarCopyPOSpunct; + case 'grammarCopyPOSadv': + return L10n.of(context)!.grammarCopyPOSadv; + case 'grammarCopyPOSaux': + return L10n.of(context)!.grammarCopyPOSaux; + case 'grammarCopyPOSspace': + return L10n.of(context)!.grammarCopyPOSspace; + case 'grammarCopyPOSsym': + return L10n.of(context)!.grammarCopyPOSsym; + case 'grammarCopyPOSdet': + return L10n.of(context)!.grammarCopyPOSdet; + case 'grammarCopyPOSpron': + return L10n.of(context)!.grammarCopyPOSpron; + case 'grammarCopyPOSadp': + return L10n.of(context)!.grammarCopyPOSadp; + case 'grammarCopyPOSpropn': + return L10n.of(context)!.grammarCopyPOSpropn; + case 'grammarCopyPOSnoun': + return L10n.of(context)!.grammarCopyPOSnoun; + case 'grammarCopyPOSintj': + return L10n.of(context)!.grammarCopyPOSintj; + case 'grammarCopyPOSx': + return L10n.of(context)!.grammarCopyPOSx; + case 'grammarCopyGENDERfem': + return L10n.of(context)!.grammarCopyGENDERfem; + case 'grammarCopyPERSON2': + return L10n.of(context)!.grammarCopyPERSON2; + case 'grammarCopyMOODimp': + return L10n.of(context)!.grammarCopyMOODimp; + case 'grammarCopyPUNCTTYPEqest': + return L10n.of(context)!.grammarCopyPUNCTTYPEqest; + case 'grammarCopyASPECTperf': + return L10n.of(context)!.grammarCopyASPECTperf; + case 'grammarCopyCASEaccnom': + return L10n.of(context)!.grammarCopyCASEaccnom; + case 'grammarCopyCASEobl': + return L10n.of(context)!.grammarCopyCASEobl; + case 'grammarCopyVOICEact': + return L10n.of(context)!.grammarCopyVOICEact; + case 'grammarCopyPUNCTTYPEbrck': + return L10n.of(context)!.grammarCopyPUNCTTYPEbrck; + case 'grammarCopyNOUNTYPEart': + return L10n.of(context)!.grammarCopyNOUNTYPEart; + case 'grammarCopyNUMBERsing': + return L10n.of(context)!.grammarCopyNUMBERsing; + case 'grammarCopyGENDERmasc': + return L10n.of(context)!.grammarCopyGENDERmasc; + case 'grammarCopyVERBTYPEmod': + return L10n.of(context)!.grammarCopyVERBTYPEmod; + case 'grammarCopyADVTYPEadverbial': + return L10n.of(context)!.grammarCopyADVTYPEadverbial; + case 'grammarCopyTENSEperi': + return L10n.of(context)!.grammarCopyTENSEperi; + case 'grammarCopyNUMFORMdigit': + return L10n.of(context)!.grammarCopyNUMFORMdigit; + case 'grammarCopyNOUNTYPEnot_proper': + return L10n.of(context)!.grammarCopyNOUNTYPEnot_proper; + case 'grammarCopyNUMTYPEcard': + return L10n.of(context)!.grammarCopyNUMTYPEcard; + case 'grammarCopyNOUNTYPEprop': + return L10n.of(context)!.grammarCopyNOUNTYPEprop; + case 'grammarCopyPUNCTTYPEdash': + return L10n.of(context)!.grammarCopyPUNCTTYPEdash; + case 'grammarCopyPUNCTTYPEyes': + return L10n.of(context)!.grammarCopyPUNCTTYPEyes; + case 'grammarCopyPUNCTTYPEsemi': + return L10n.of(context)!.grammarCopyPUNCTTYPEsemi; + case 'grammarCopyPUNCTTYPEcomm': + return L10n.of(context)!.grammarCopyPUNCTTYPEcomm; + case 'grammarCopyMOODcnd': + return L10n.of(context)!.grammarCopyMOODcnd; + case 'grammarCopyCASEacc': + return L10n.of(context)!.grammarCopyCASEacc; + case 'grammarCopyPARTTYPEpart': + return L10n.of(context)!.grammarCopyPARTTYPEpart; + case 'grammarCopyTENSEpast': + return L10n.of(context)!.grammarCopyTENSEpast; + case 'grammarCopyDEGREEsup': + return L10n.of(context)!.grammarCopyDEGREEsup; + case 'grammarCopyPUNCTTYPEcolo': + return L10n.of(context)!.grammarCopyPUNCTTYPEcolo; + case 'grammarCopyPERSON3': + return L10n.of(context)!.grammarCopyPERSON3; + case 'grammarCopyNUMBERplur': + return L10n.of(context)!.grammarCopyNUMBERplur; + case 'grammarCopyPRONTYPEnpr': + return L10n.of(context)!.grammarCopyPRONTYPEnpr; + case 'grammarCopyPRONTYPEinterrogative': + return L10n.of(context)!.grammarCopyPRONTYPEinterrogative; + case 'grammarCopyPOLITEinfm': + return L10n.of(context)!.grammarCopyPOLITEinfm; + case 'grammarCopyADVTYPEtim': + return L10n.of(context)!.grammarCopyADVTYPEtim; + case 'grammarCopyPOLARITYneg': + return L10n.of(context)!.grammarCopyPOLARITYneg; + case 'grammarCopyNUMTYPEtot': + return L10n.of(context)!.grammarCopyNUMTYPEtot; + case 'grammarCopyADVTYPEadnomial': + return L10n.of(context)!.grammarCopyADVTYPEadnomial; + case 'grammarCopyASPECTprog': + return L10n.of(context)!.grammarCopyASPECTprog; + case 'grammarCopyMOODsub': + return L10n.of(context)!.grammarCopyMOODsub; + case 'grammarCopyVERBFORMcomplementive': + return L10n.of(context)!.grammarCopyVERBFORMcomplementive; + case 'grammarCopyCASEnom': + return L10n.of(context)!.grammarCopyCASEnom; + case 'grammarCopyTENSEfut': + return L10n.of(context)!.grammarCopyTENSEfut; + case 'grammarCopyCASEdat': + return L10n.of(context)!.grammarCopyCASEdat; + case 'grammarCopyTENSEpres': + return L10n.of(context)!.grammarCopyTENSEpres; + case 'grammarCopyGENDERneut': + return L10n.of(context)!.grammarCopyGENDERneut; + case 'grammarCopyPRONTYPErel': + return L10n.of(context)!.grammarCopyPRONTYPErel; + case 'grammarCopyVERBFORMfinalEnding': + return L10n.of(context)!.grammarCopyVERBFORMfinalEnding; + case 'grammarCopyPRONTYPEdem': + return L10n.of(context)!.grammarCopyPRONTYPEdem; + case 'grammarCopyPREPCASEpre': + return L10n.of(context)!.grammarCopyPREPCASEpre; + case 'grammarCopyVERBFORMfin': + return L10n.of(context)!.grammarCopyVERBFORMfin; + case 'grammarCopyDEGREEpos': + return L10n.of(context)!.grammarCopyDEGREEpos; + case 'grammarCopyPUNCTTYPEquot': + return L10n.of(context)!.grammarCopyPUNCTTYPEquot; + case 'grammarCopyVERBFORMger': + return L10n.of(context)!.grammarCopyVERBFORMger; + case 'grammarCopyVOICEpass': + return L10n.of(context)!.grammarCopyVOICEpass; + case 'grammarCopyCASEgen': + return L10n.of(context)!.grammarCopyCASEgen; + case 'grammarCopyTENSEprs': + return L10n.of(context)!.grammarCopyTENSEprs; + case 'grammarCopyDEFINITEdef': + return L10n.of(context)!.grammarCopyDEFINITEdef; + case 'grammarCopyNUMTYPEord': + return L10n.of(context)!.grammarCopyNUMTYPEord; + case 'grammarCopyCASEins': + return L10n.of(context)!.grammarCopyCASEins; + case 'grammarCopyVERBFORMinf': + return L10n.of(context)!.grammarCopyVERBFORMinf; + case 'grammarCopyNUMFORMlong': + return L10n.of(context)!.grammarCopyNUMFORMlong; + case 'grammarCopyCASEloc': + return L10n.of(context)!.grammarCopyCASEloc; + case 'grammarCopyMOODind': + return L10n.of(context)!.grammarCopyMOODind; + case 'grammarCopyDEGREEcmp': + return L10n.of(context)!.grammarCopyDEGREEcmp; + case 'grammarCopyCASErelativeCase': + return L10n.of(context)!.grammarCopyCASErelativeCase; + case 'grammarCopyPUNCTTYPEexcl': + return L10n.of(context)!.grammarCopyPUNCTTYPEexcl; + case 'grammarCopyPERSON1': + return L10n.of(context)!.grammarCopyPERSON1; + case 'grammarCopyPUNCTSIDEini': + return L10n.of(context)!.grammarCopyPUNCTSIDEini; + case 'grammarCopyGENDERperson': + return L10n.of(context)!.grammarCopyGENDERperson; + case 'grammarCopyFOREIGNyes': + return L10n.of(context)!.grammarCopyFOREIGNyes; + case 'grammarCopyVOICEvoice': + return L10n.of(context)!.grammarCopyVOICEvoice; + case 'grammarCopyVERBTYPEverbType': + return L10n.of(context)!.grammarCopyVERBTYPEverbType; + case 'grammarCopyPOSSpass': + return L10n.of(context)!.grammarCopyPOSSpass; + case 'grammarCopyPREPCASEprepCase': + return L10n.of(context)!.grammarCopyPREPCASEprepCase; + case 'grammarCopyNUMTYPEnumType': + return L10n.of(context)!.grammarCopyNUMTYPEnumType; + case 'grammarCopyNOUNTYPEnounType': + return L10n.of(context)!.grammarCopyNOUNTYPEnounType; + case 'grammarCopyREFLEXreflex': + return L10n.of(context)!.grammarCopyREFLEXreflex; + case 'grammarCopyPRONTYPEpronType': + return L10n.of(context)!.grammarCopyPRONTYPEpronType; + case 'grammarCopyPUNCTSIDEpunctSide': + return L10n.of(context)!.grammarCopyPUNCTSIDEpunctSide; + case 'grammarCopyVERBFORMverbForm': + return L10n.of(context)!.grammarCopyVERBFORMverbForm; + case 'grammarCopyGENDERgender': + return L10n.of(context)!.grammarCopyGENDERgender; + case 'grammarCopyMOODmood': + return L10n.of(context)!.grammarCopyMOODmood; + case 'grammarCopyASPECTaspect': + return L10n.of(context)!.grammarCopyASPECTaspect; + case 'grammarCopyPUNCTTYPEpunctType': + return L10n.of(context)!.grammarCopyPUNCTTYPEpunctType; + case 'grammarCopyTENSEtense': + return L10n.of(context)!.grammarCopyTENSEtense; + case 'grammarCopyDEGREEdegree': + return L10n.of(context)!.grammarCopyDEGREEdegree; + case 'grammarCopyPOLITEpolite': + return L10n.of(context)!.grammarCopyPOLITEpolite; + case 'grammarCopyADVTYPEadvType': + return L10n.of(context)!.grammarCopyADVTYPEadvType; + case 'grammarCopyNUMFORMnumber': + return L10n.of(context)!.grammarCopyNUMFORMnumber; + case 'grammarCopyCONJTYPEconjType': + return L10n.of(context)!.grammarCopyCONJTYPEconjType; + case 'grammarCopyPOLARITYpolarity': + return L10n.of(context)!.grammarCopyPOLARITYpolarity; + case 'grammarCopyCASEcase': + return L10n.of(context)!.grammarCopyCASEcase; + case 'grammarCopyDEFINITEdefinite': + return L10n.of(context)!.grammarCopyDEFINITEdefinite; + case 'grammarCopyNUMFORMnumForm': + return L10n.of(context)!.grammarCopyNUMFORMnumForm; + case 'grammarCopyPRONTYPEadn': + return L10n.of(context)!.grammarCopyPRONTYPEadn; + case 'grammarCopyVOCvoc': + return L10n.of(context)!.grammarCopyVOCvoc; + case 'grammarCopyCMPLcmpl': + return L10n.of(context)!.grammarCopyCMPLcmpl; + case 'grammarCopyADVadv': + return L10n.of(context)!.grammarCopyADVadv; + case 'grammarCopyMOODjus': + return L10n.of(context)!.grammarCopyMOODjus; + case 'grammarCopyGENDERcom': + return L10n.of(context)!.grammarCopyGENDERcom; + case 'grammarCopyREFLEXrflx': + return L10n.of(context)!.grammarCopyREFLEXrflx; + case 'grammarCopyPARTTYPEpar': + return L10n.of(context)!.grammarCopyPARTTYPEpar; + case 'grammarCopySPCspc': + return L10n.of(context)!.grammarCopySPCspc; + case 'grammarCopyTENSEpqp': + return L10n.of(context)!.grammarCopyTENSEpqp; + case 'grammarCopyREFLEXref': + return L10n.of(context)!.grammarCopyREFLEXref; + case 'grammarCopyPUNCTTYPEnshrt': + return L10n.of(context)!.grammarCopyPUNCTTYPEnshrt; + case 'grammarCopyNUMBERdual': + return L10n.of(context)!.grammarCopyNUMBERdual; + case 'grammarCopyNUMFORMlng': + return L10n.of(context)!.grammarCopyNUMFORMlng; + case 'grammarCopyVOICEmid': + return L10n.of(context)!.grammarCopyVOICEmid; + case 'grammarCopyINTRELintRel': + return L10n.of(context)!.grammarCopyINTRELintRel; + case 'grammarCopyINTint': + return L10n.of(context)!.grammarCopyINTint; + case 'grammarCopyVOICEcaus': + return L10n.of(context)!.grammarCopyVOICEcaus; + case 'grammarCopyUNKNOWNunknown': + return L10n.of(context)!.grammarCopyUnknown; + case 'grammarCopyEVIDENTevident': + return L10n.of(context)!.grammarCopyEVIDENTevident; + case 'grammarCopyNUMFORMnumberPsor': + return L10n.of(context)!.grammarCopyNUMFORMnumberPsor; + case 'grammarCopyASPECThab': + return L10n.of(context)!.grammarCopyASPECThab; + case 'grammarCopyCASEabl': + return L10n.of(context)!.grammarCopyCASEabl; + case 'grammarCopyCASEall': + return L10n.of(context)!.grammarCopyCASEall; + case 'grammarCopyCASEess': + return L10n.of(context)!.grammarCopyCASEess; + case 'grammarCopyCASEtra': + return L10n.of(context)!.grammarCopyCASEtra; + case 'grammarCopyCASEequ': + return L10n.of(context)!.grammarCopyCASEequ; + case 'grammarCopyCASEdis': + return L10n.of(context)!.grammarCopyCASEdis; + case 'grammarCopyCASEabs': + return L10n.of(context)!.grammarCopyCASEabs; + case 'grammarCopyCASEerg': + return L10n.of(context)!.grammarCopyCASEerg; + case 'grammarCopyCASEcau': + return L10n.of(context)!.grammarCopyCASEcau; + case 'grammarCopyCASEben': + return L10n.of(context)!.grammarCopyCASEben; + case 'grammarCopyCASEtem': + return L10n.of(context)!.grammarCopyCASEtem; + case 'grammarCopyCONJTYPEcoord': + return L10n.of(context)!.grammarCopyCONJTYPEcoord; + case 'grammarCopyDEFINITEcons': + return L10n.of(context)!.grammarCopyDEFINITEcons; + case 'grammarCopyDEGREEabs': + return L10n.of(context)!.grammarCopyDEGREEabs; + case 'grammarCopyEVIDENTfh': + return L10n.of(context)!.grammarCopyEVIDENTfh; + case 'grammarCopyEVIDENTnfh': + return L10n.of(context)!.grammarCopyEVIDENTnfh; + case 'grammarCopyMOODopt': + return L10n.of(context)!.grammarCopyMOODopt; + case 'grammarCopyMOODadm': + return L10n.of(context)!.grammarCopyMOODadm; + case 'grammarCopyMOODdes': + return L10n.of(context)!.grammarCopyMOODdes; + case 'grammarCopyMOODnec': + return L10n.of(context)!.grammarCopyMOODnec; + case 'grammarCopyMOODpot': + return L10n.of(context)!.grammarCopyMOODpot; + case 'grammarCopyMOODprp': + return L10n.of(context)!.grammarCopyMOODprp; + case 'grammarCopyMOODqot': + return L10n.of(context)!.grammarCopyMOODqot; + case 'grammarCopyNUMFORMword': + return L10n.of(context)!.grammarCopyNUMFORMword; + case 'grammarCopyNUMFORMroman': + return L10n.of(context)!.grammarCopyNUMFORMroman; + case 'grammarCopyNUMFORMletter': + return L10n.of(context)!.grammarCopyNUMFORMletter; + case 'grammarCopyNUMTYPEmult': + return L10n.of(context)!.grammarCopyNUMTYPEmult; + case 'grammarCopyNUMTYPEfrac': + return L10n.of(context)!.grammarCopyNUMTYPEfrac; + case 'grammarCopyNUMTYPEsets': + return L10n.of(context)!.grammarCopyNUMTYPEsets; + case 'grammarCopyNUMTYPErange': + return L10n.of(context)!.grammarCopyNUMTYPErange; + case 'grammarCopyNUMTYPEdist': + return L10n.of(context)!.grammarCopyNUMTYPEdist; + case 'grammarCopyNUMBERtri': + return L10n.of(context)!.grammarCopyNUMBERtri; + case 'grammarCopyNUMBERpauc': + return L10n.of(context)!.grammarCopyNUMBERpauc; + case 'grammarCopyNUMBERgrpa': + return L10n.of(context)!.grammarCopyNUMBERgrpa; + case 'grammarCopyNUMBERgrpl': + return L10n.of(context)!.grammarCopyNUMBERgrpl; + case 'grammarCopyNUMBERinv': + return L10n.of(context)!.grammarCopyNUMBERinv; + case 'grammarCopyPERSON0': + return L10n.of(context)!.grammarCopyPERSON0; + case 'grammarCopyPERSON4': + return L10n.of(context)!.grammarCopyPERSON4; + case 'grammarCopyPOLITEform': + return L10n.of(context)!.grammarCopyPOLITEform; + case 'grammarCopyPOLITEelev': + return L10n.of(context)!.grammarCopyPOLITEelev; + case 'grammarCopyPOLITEhumb': + return L10n.of(context)!.grammarCopyPOLITEhumb; + case 'grammarCopyPRONTYPEemp': + return L10n.of(context)!.grammarCopyPRONTYPEemp; + case 'grammarCopyPRONTYPEexc': + return L10n.of(context)!.grammarCopyPRONTYPEexc; + case 'grammarCopyPRONTYPErcp': + return L10n.of(context)!.grammarCopyPRONTYPErcp; + case 'grammarCopyPRONTYPEintRelPronType': + return L10n.of(context)!.grammarCopyPRONTYPEintRelPronType; + case 'grammarCopyTENSEaor': + return L10n.of(context)!.grammarCopyTENSEaor; + case 'grammarCopyTENSEeps': + return L10n.of(context)!.grammarCopyTENSEeps; + case 'grammarCopyTENSEprosp': + return L10n.of(context)!.grammarCopyTENSEprosp; + case 'grammarCopyVERBFORMpart': + return L10n.of(context)!.grammarCopyVERBFORMpart; + case 'grammarCopyVERBFORMconv': + return L10n.of(context)!.grammarCopyVERBFORMconv; + case 'grammarCopyVERBFORMvnoun': + return L10n.of(context)!.grammarCopyVERBFORMvnoun; + case 'grammarCopyVOICEantip': + return L10n.of(context)!.grammarCopyVOICEantip; + case 'grammarCopyVOICEcauVoice': + return L10n.of(context)!.grammarCopyVOICEcauVoice; + case 'grammarCopyVOICedir': + return L10n.of(context)!.grammarCopyVOICedir; + case 'grammarCopyVOICEinvVoice': + return L10n.of(context)!.grammarCopyVOICEinvVoice; + case 'grammarCopyVOICErcpVoice': + return L10n.of(context)!.grammarCopyVOICErcpVoice; // Handle empty tag case '': ErrorHandler.logError( @@ -255,13 +410,13 @@ String getGrammarCopy(String tag, BuildContext context) { default: debugger(when: kDebugMode); ErrorHandler.logError( - e: Exception('Need to add copy for $tag to intl_en.arb'), - m: 'Need to add copy for $tag to intl_en.arb', + e: Exception('Need to add copy for $key to intl_en.arb'), + m: 'Need to add copy for $key to intl_en.arb', data: { - 'tag': tag, + 'tag': key, 'context': context, }, ); - return tag; // Fallback to the tag itself if no match is found + return key; // Fallback to the key itself if no match is found } } From 71b090683d4f2a1749ab119b9619dc5c7aeb9b9d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 09:51:09 -0500 Subject: [PATCH 05/13] use ConstructIdentifier to sort constructs into groups --- lib/pangea/models/analytics/construct_list_model.dart | 9 ++------- lib/pangea/models/analytics/constructs_model.dart | 7 +++++++ .../practice_activity_model.dart | 5 ++++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/pangea/models/analytics/construct_list_model.dart b/lib/pangea/models/analytics/construct_list_model.dart index 747a54bb4..80de03f53 100644 --- a/lib/pangea/models/analytics/construct_list_model.dart +++ b/lib/pangea/models/analytics/construct_list_model.dart @@ -36,13 +36,8 @@ class ConstructListModel { final Map> lemmaToUses = {}; for (final use in uses) { if (use.lemma == null) continue; - lemmaToUses[use.lemma! + - use.constructType.string + - (use.category ?? "Other")] ??= []; - lemmaToUses[use.lemma! + - use.constructType.string + - (use.category ?? "Other")]! - .add(use); + lemmaToUses[use.identifier.string] ??= []; + lemmaToUses[use.identifier.string]!.add(use); } _constructMap = lemmaToUses.map( diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index e4e006952..12e6b74c8 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; @@ -161,6 +162,12 @@ class OneConstructUse { } int get pointValue => useType.pointValue; + + ConstructIdentifier get identifier => ConstructIdentifier( + lemma: lemma!, + type: constructType, + category: category, + ); } class ConstructUseMetaData { diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index ccdd3802a..e5048400d 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -12,7 +12,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; class ConstructIdentifier { final String lemma; final ConstructTypeEnum type; - String? category; + final String? category; ConstructIdentifier({ required this.lemma, @@ -68,6 +68,9 @@ class ConstructIdentifier { int get hashCode { return lemma.hashCode ^ type.hashCode; } + + String get string => + "$lemma-${type.string}${category != null ? "-$category" : "-other"}"; } class CandidateMessage { From d904c59d6a0d0835aef34e441aa2036ec548f519 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 10:25:06 -0500 Subject: [PATCH 06/13] added xp number to xp progress bar --- lib/pangea/utils/get_grammar_copy.dart | 14 ++++--- .../analytics_summary/analytics_popup.dart | 38 +++++++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index 3e89bd65a..cb9996959 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -5,12 +5,16 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -String getGrammarCopy( - {required String category, - required String feature, - required BuildContext context}) { +/// Used on morph constructs +String getGrammarCopy({ + required String category, + + /// This is the tag / feature + required String lemma, + required BuildContext context, +}) { final String key = - 'grammarCopy${category.toUpperCase()}${feature.toLowerCase()}'; + 'grammarCopy${category.toUpperCase()}${lemma.toLowerCase()}'; switch (key) { case 'grammarCopyPOSsconj': diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart index ff29fc118..8870bd7aa 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -66,11 +66,8 @@ class AnalyticsPopup extends StatelessWidget { return Column( children: [ ExpansionTile( - title: Text( - category.key != 'Other' - ? getGrammarCopy(category.key, context) - : category.key, - ), + // GABBY TODO switch back to getGrammarCopy once it's updated + title: Text(category.key), children: category.value.map((constructUses) { return ConstructUsesXPTile( indicator: indicator, @@ -127,23 +124,34 @@ class ConstructUsesXPTile extends StatelessWidget { @override Widget build(BuildContext context) { - final lemma = constructUses.lemma; return Tooltip( message: "${constructUses.points} / ${constructsModel.maxXPPerLemma}", child: ListTile( onTap: () {}, title: Text( constructsModel.type == ConstructTypeEnum.morph - ? getGrammarCopy(lemma, context) - : lemma, + ? getGrammarCopy( + category: constructUses.category, + lemma: constructUses.lemma, + context: context, + ) + : constructUses.lemma, ), - subtitle: LinearProgressIndicator( - value: constructUses.points / constructsModel.maxXPPerLemma, - minHeight: 20, - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: indicator.color(context), + subtitle: Row( + children: [ + Expanded( + child: LinearProgressIndicator( + value: constructUses.points / constructsModel.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, From e7e53675950dd7e63a7eb2927b085e1cedfa25c2 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 12:21:50 -0500 Subject: [PATCH 07/13] added some missing grammar copy --- .../enum/analytics/morph_categories_enum.dart | 127 ++++++++++++++++++ .../enum/analytics/parts_of_speech_enum.dart | 87 ++++++++++++ lib/pangea/enum/construct_type_enum.dart | 14 ++ lib/pangea/utils/get_grammar_copy.dart | 34 ++++- .../analytics_summary/analytics_popup.dart | 18 ++- 5 files changed, 272 insertions(+), 8 deletions(-) create mode 100644 lib/pangea/enum/analytics/morph_categories_enum.dart create mode 100644 lib/pangea/enum/analytics/parts_of_speech_enum.dart diff --git a/lib/pangea/enum/analytics/morph_categories_enum.dart b/lib/pangea/enum/analytics/morph_categories_enum.dart new file mode 100644 index 000000000..6b52055d8 --- /dev/null +++ b/lib/pangea/enum/analytics/morph_categories_enum.dart @@ -0,0 +1,127 @@ +// ignore_for_file: constant_identifier_names + +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +enum MorphologicalCategories { + Pos, + AdvType, + Aspect, + Case, + ConjType, + Definite, + Degree, + Evident, + Foreign, + Gender, + Mood, + NounType, + NumForm, + NumType, + Number, + NumberPsor, + Person, + Polarity, + Polite, + Poss, + PrepCase, + PronType, + PunctSide, + PunctType, + Reflex, + Tense, + VerbForm, + VerbType, + Voice, +} + +extension MorphologicalCategoriesExtension on MorphologicalCategories { + /// Convert enum to string + String toShortString() { + return toString().split('.').last; + } + + /// Convert string to enum + static MorphologicalCategories? fromString(String category) { + return MorphologicalCategories.values.firstWhereOrNull( + (e) => e.toShortString() == category, + ); + } + + String getDisplayCopy(BuildContext context) { + switch (this) { + case MorphologicalCategories.Pos: + return L10n.of(context)!.grammarCopyPOS; + case MorphologicalCategories.AdvType: + return L10n.of(context)!.grammarCopyADVTYPE; + case MorphologicalCategories.Aspect: + return L10n.of(context)!.grammarCopyASPECT; + case MorphologicalCategories.Case: + return L10n.of(context)!.grammarCopyCASE; + case MorphologicalCategories.ConjType: + return L10n.of(context)!.grammarCopyCONJTYPE; + case MorphologicalCategories.Definite: + return L10n.of(context)!.grammarCopyDEFINITE; + case MorphologicalCategories.Degree: + return L10n.of(context)!.grammarCopyDEGREE; + case MorphologicalCategories.Evident: + return L10n.of(context)!.grammarCopyEVIDENT; + case MorphologicalCategories.Foreign: + return L10n.of(context)!.grammarCopyFOREIGN; + case MorphologicalCategories.Gender: + return L10n.of(context)!.grammarCopyGENDER; + case MorphologicalCategories.Mood: + return L10n.of(context)!.grammarCopyMOOD; + case MorphologicalCategories.NounType: + return L10n.of(context)!.grammarCopyNOUNTYPE; + case MorphologicalCategories.NumForm: + return L10n.of(context)!.grammarCopyNUMFORM; + case MorphologicalCategories.NumType: + return L10n.of(context)!.grammarCopyNUMTYPE; + case MorphologicalCategories.Number: + return L10n.of(context)!.grammarCopyNUMBER; + case MorphologicalCategories.NumberPsor: + return L10n.of(context)!.grammarCopyNUMBERPSOR; + case MorphologicalCategories.Person: + return L10n.of(context)!.grammarCopyPERSON; + case MorphologicalCategories.Polarity: + return L10n.of(context)!.grammarCopyPOLARITY; + case MorphologicalCategories.Polite: + return L10n.of(context)!.grammarCopyPOLITE; + case MorphologicalCategories.Poss: + return L10n.of(context)!.grammarCopyPOSS; + case MorphologicalCategories.PrepCase: + return L10n.of(context)!.grammarCopyPREPCASE; + case MorphologicalCategories.PronType: + return L10n.of(context)!.grammarCopyPRONTYPE; + case MorphologicalCategories.PunctSide: + return L10n.of(context)!.grammarCopyPUNCTSIDE; + case MorphologicalCategories.PunctType: + return L10n.of(context)!.grammarCopyPUNCTTYPE; + case MorphologicalCategories.Reflex: + return L10n.of(context)!.grammarCopyREFLEX; + case MorphologicalCategories.Tense: + return L10n.of(context)!.grammarCopyTENSE; + case MorphologicalCategories.VerbForm: + return L10n.of(context)!.grammarCopyVERBFORM; + case MorphologicalCategories.VerbType: + return L10n.of(context)!.grammarCopyVERBTYPE; + case MorphologicalCategories.Voice: + return L10n.of(context)!.grammarCopyVOICE; + } + } +} + +String? getMorphologicalCategoryCopy( + String categoryName, + BuildContext context, +) { + final MorphologicalCategories? category = + MorphologicalCategoriesExtension.fromString(categoryName); + + if (category == null) { + return null; + } + return category.getDisplayCopy(context); +} diff --git a/lib/pangea/enum/analytics/parts_of_speech_enum.dart b/lib/pangea/enum/analytics/parts_of_speech_enum.dart new file mode 100644 index 000000000..5348e938b --- /dev/null +++ b/lib/pangea/enum/analytics/parts_of_speech_enum.dart @@ -0,0 +1,87 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +enum GrammarCopyPOS { + sconj, + num, + verb, + affix, + part, + adj, + cconj, + punct, + adv, + aux, + space, + sym, + det, + pron, + adp, + propn, + noun, + intj, + x, +} + +extension GrammarCopyPOSExtension on GrammarCopyPOS { + /// Convert enum to string + String toShortString() { + return toString().split('.').last.toLowerCase(); + } + + GrammarCopyPOS? fromString(String categoryName) { + return GrammarCopyPOS.values.firstWhereOrNull( + (pos) => pos.toShortString() == categoryName.toLowerCase(), + ); + } + + String getDisplayCopy(BuildContext context) { + switch (this) { + case GrammarCopyPOS.sconj: + return L10n.of(context)!.grammarCopyPOSsconj; + case GrammarCopyPOS.num: + return L10n.of(context)!.grammarCopyPOSnum; + case GrammarCopyPOS.verb: + return L10n.of(context)!.grammarCopyPOSverb; + case GrammarCopyPOS.affix: + return L10n.of(context)!.grammarCopyPOSaffix; + case GrammarCopyPOS.part: + return L10n.of(context)!.grammarCopyPOSpart; + case GrammarCopyPOS.adj: + return L10n.of(context)!.grammarCopyPOSadj; + case GrammarCopyPOS.cconj: + return L10n.of(context)!.grammarCopyPOScconj; + case GrammarCopyPOS.punct: + return L10n.of(context)!.grammarCopyPOSpunct; + case GrammarCopyPOS.adv: + return L10n.of(context)!.grammarCopyPOSadv; + case GrammarCopyPOS.aux: + return L10n.of(context)!.grammarCopyPOSaux; + case GrammarCopyPOS.space: + return L10n.of(context)!.grammarCopyPOSspace; + case GrammarCopyPOS.sym: + return L10n.of(context)!.grammarCopyPOSsym; + case GrammarCopyPOS.det: + return L10n.of(context)!.grammarCopyPOSdet; + case GrammarCopyPOS.pron: + return L10n.of(context)!.grammarCopyPOSpron; + case GrammarCopyPOS.adp: + return L10n.of(context)!.grammarCopyPOSadp; + case GrammarCopyPOS.propn: + return L10n.of(context)!.grammarCopyPOSpropn; + case GrammarCopyPOS.noun: + return L10n.of(context)!.grammarCopyPOSnoun; + case GrammarCopyPOS.intj: + return L10n.of(context)!.grammarCopyPOSintj; + case GrammarCopyPOS.x: + return L10n.of(context)!.grammarCopyPOSx; + } + } +} + +String? getVocabCategoryName(String category, BuildContext context) { + return GrammarCopyPOS.values + .firstWhereOrNull((pos) => pos.toShortString() == category.toLowerCase()) + ?.getDisplayCopy(context); +} diff --git a/lib/pangea/enum/construct_type_enum.dart b/lib/pangea/enum/construct_type_enum.dart index 2b346b235..19d3641f1 100644 --- a/lib/pangea/enum/construct_type_enum.dart +++ b/lib/pangea/enum/construct_type_enum.dart @@ -1,4 +1,7 @@ import 'package:fluffychat/pangea/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/enum/analytics/morph_categories_enum.dart'; +import 'package:fluffychat/pangea/enum/analytics/parts_of_speech_enum.dart'; +import 'package:flutter/material.dart'; enum ConstructTypeEnum { grammar, @@ -28,6 +31,17 @@ extension ConstructExtension on ConstructTypeEnum { return AnalyticsConstants.morphUseMaxXP; } } + + String? getDisplayCopy(String category, BuildContext context) { + switch (this) { + case ConstructTypeEnum.morph: + return getMorphologicalCategoryCopy(category, context); + case ConstructTypeEnum.vocab: + return getVocabCategoryName(category, context); + default: + return null; + } + } } class ConstructTypeUtil { diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index cb9996959..cdcdcb3d6 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -1,3 +1,5 @@ +// ignore_for_file: constant_identifier_names + import 'dart:developer'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -6,15 +8,19 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; /// Used on morph constructs -String getGrammarCopy({ +String? getGrammarCopy({ required String category, /// This is the tag / feature required String lemma, required BuildContext context, }) { + if (category.toLowerCase() == 'other') { + return null; + } + final String key = - 'grammarCopy${category.toUpperCase()}${lemma.toLowerCase()}'; + 'grammarCopy${category.toUpperCase()}${lemma.replaceAll(",", "").toLowerCase()}'; switch (key) { case 'grammarCopyPOSsconj': @@ -119,8 +125,16 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyNUMBERplur; case 'grammarCopyPRONTYPEnpr': return L10n.of(context)!.grammarCopyPRONTYPEnpr; + case 'grammarCopyPRONTYPEprs': + return L10n.of(context)!.grammarCopyPRONTYPEprs; + case 'grammarCopyPRONTYPEind': + return L10n.of(context)!.grammarCopyPRONTYPEind; case 'grammarCopyPRONTYPEinterrogative': return L10n.of(context)!.grammarCopyPRONTYPEinterrogative; + case 'grammarCopyPRONTYPEart': + return L10n.of(context)!.grammarCopyPRONTYPEart; + case 'grammarCopyPRONTYPEtot': + return L10n.of(context)!.grammarCopyPRONTYPEtot; case 'grammarCopyPOLITEinfm': return L10n.of(context)!.grammarCopyPOLITEinfm; case 'grammarCopyADVTYPEtim': @@ -155,6 +169,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyPRONTYPEdem; case 'grammarCopyPREPCASEpre': return L10n.of(context)!.grammarCopyPREPCASEpre; + case 'grammarCopyPREPCASEnpr': + return L10n.of(context)!.grammarCopyPREPCASEnpr; case 'grammarCopyVERBFORMfin': return L10n.of(context)!.grammarCopyVERBFORMfin; case 'grammarCopyDEGREEpos': @@ -171,6 +187,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyTENSEprs; case 'grammarCopyDEFINITEdef': return L10n.of(context)!.grammarCopyDEFINITEdef; + case 'grammarCopyDEFINITEind': + return L10n.of(context)!.grammarCopyDEFINITEind; case 'grammarCopyNUMTYPEord': return L10n.of(context)!.grammarCopyNUMTYPEord; case 'grammarCopyCASEins': @@ -189,10 +207,14 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyCASErelativeCase; case 'grammarCopyPUNCTTYPEexcl': return L10n.of(context)!.grammarCopyPUNCTTYPEexcl; + case 'rammarCopyPUNCTTYPEperi': + return L10n.of(context)!.grammarCopyPUNCTTYPEperi; case 'grammarCopyPERSON1': return L10n.of(context)!.grammarCopyPERSON1; case 'grammarCopyPUNCTSIDEini': return L10n.of(context)!.grammarCopyPUNCTSIDEini; + case 'grammarCopyPUNCTSIDEfin': + return L10n.of(context)!.grammarCopyPUNCTSIDEfin; case 'grammarCopyGENDERperson': return L10n.of(context)!.grammarCopyGENDERperson; case 'grammarCopyFOREIGNyes': @@ -203,6 +225,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyVERBTYPEverbType; case 'grammarCopyPOSSpass': return L10n.of(context)!.grammarCopyPOSSpass; + case 'grammarCopyPOSSyes': + return L10n.of(context)!.grammarCopyPOSSyes; case 'grammarCopyPREPCASEprepCase': return L10n.of(context)!.grammarCopyPREPCASEprepCase; case 'grammarCopyNUMTYPEnumType': @@ -259,6 +283,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyGENDERcom; case 'grammarCopyREFLEXrflx': return L10n.of(context)!.grammarCopyREFLEXrflx; + case 'grammarCopyREFLEXyes': + return L10n.of(context)!.grammarCopyREFLEXyes; case 'grammarCopyPARTTYPEpar': return L10n.of(context)!.grammarCopyPARTTYPEpar; case 'grammarCopySPCspc': @@ -377,6 +403,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyPRONTYPEexc; case 'grammarCopyPRONTYPErcp': return L10n.of(context)!.grammarCopyPRONTYPErcp; + case 'grammarCopyPRONTYPEintrel': + return L10n.of(context)!.grammarCopyPRONTYPEintrel; case 'grammarCopyPRONTYPEintRelPronType': return L10n.of(context)!.grammarCopyPRONTYPEintRelPronType; case 'grammarCopyTENSEaor': @@ -385,6 +413,8 @@ String getGrammarCopy({ return L10n.of(context)!.grammarCopyTENSEeps; case 'grammarCopyTENSEprosp': return L10n.of(context)!.grammarCopyTENSEprosp; + case 'grammarCopyTENSEimp': + return L10n.of(context)!.grammarCopyTENSEimp; case 'grammarCopyVERBFORMpart': return L10n.of(context)!.grammarCopyVERBFORMpart; case 'grammarCopyVERBFORMconv': diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart index 8870bd7aa..5eda9c97c 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -66,8 +66,13 @@ class AnalyticsPopup extends StatelessWidget { return Column( children: [ ExpansionTile( - // GABBY TODO switch back to getGrammarCopy once it's updated - title: Text(category.key), + title: Text( + category.value.first.constructType.getDisplayCopy( + category.key, + context, + ) ?? + category.key, + ), children: category.value.map((constructUses) { return ConstructUsesXPTile( indicator: indicator, @@ -131,10 +136,11 @@ class ConstructUsesXPTile extends StatelessWidget { title: Text( constructsModel.type == ConstructTypeEnum.morph ? getGrammarCopy( - category: constructUses.category, - lemma: constructUses.lemma, - context: context, - ) + category: constructUses.category, + lemma: constructUses.lemma, + context: context, + ) ?? + constructUses.lemma : constructUses.lemma, ), subtitle: Row( From 4c26e4629a359f271ca08438f49053f05e1d4f2d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 12:30:37 -0500 Subject: [PATCH 08/13] more grammar copy updates --- lib/pangea/enum/analytics/morph_categories_enum.dart | 6 ++++-- lib/pangea/utils/get_grammar_copy.dart | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/pangea/enum/analytics/morph_categories_enum.dart b/lib/pangea/enum/analytics/morph_categories_enum.dart index 6b52055d8..677f58fa3 100644 --- a/lib/pangea/enum/analytics/morph_categories_enum.dart +++ b/lib/pangea/enum/analytics/morph_categories_enum.dart @@ -39,13 +39,15 @@ enum MorphologicalCategories { extension MorphologicalCategoriesExtension on MorphologicalCategories { /// Convert enum to string String toShortString() { - return toString().split('.').last; + return toString().split('.').last.toLowerCase(); } /// Convert string to enum static MorphologicalCategories? fromString(String category) { return MorphologicalCategories.values.firstWhereOrNull( - (e) => e.toShortString() == category, + (e) => + e.toShortString() == + category.toLowerCase().replaceAll(RegExp(r'[,\[\]]'), ''), ); } diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index cdcdcb3d6..86c36be30 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -20,7 +20,7 @@ String? getGrammarCopy({ } final String key = - 'grammarCopy${category.toUpperCase()}${lemma.replaceAll(",", "").toLowerCase()}'; + 'grammarCopy${category.replaceAll(RegExp(r'[,\[\]]'), '').toUpperCase()}${lemma.replaceAll(RegExp(r'[,\[\]]'), '').toLowerCase()}'; switch (key) { case 'grammarCopyPOSsconj': @@ -81,6 +81,12 @@ String? getGrammarCopy({ return L10n.of(context)!.grammarCopyPUNCTTYPEbrck; case 'grammarCopyNOUNTYPEart': return L10n.of(context)!.grammarCopyNOUNTYPEart; + case 'grammarCopyNUMBERPSORsing': + return L10n.of(context)!.grammarCopyNUMBERPSORsing; + case 'grammarCopyNUMBERPSORplur': + return L10n.of(context)!.grammarCopyNUMBERPSORplur; + case 'grammarCopyNUMBERPSORdual': + return L10n.of(context)!.grammarCopyNUMBERPSORdual; case 'grammarCopyNUMBERsing': return L10n.of(context)!.grammarCopyNUMBERsing; case 'grammarCopyGENDERmasc': From 506629b07fd1d0b57dad77ef50474f773e295c15 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 12:42:36 -0500 Subject: [PATCH 09/13] long sentry error on missing grammar copy --- lib/pangea/enum/analytics/morph_categories_enum.dart | 11 ++++++++++- lib/pangea/enum/analytics/parts_of_speech_enum.dart | 11 ++++++++++- lib/pangea/utils/get_grammar_copy.dart | 3 +-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/pangea/enum/analytics/morph_categories_enum.dart b/lib/pangea/enum/analytics/morph_categories_enum.dart index 677f58fa3..1642f0945 100644 --- a/lib/pangea/enum/analytics/morph_categories_enum.dart +++ b/lib/pangea/enum/analytics/morph_categories_enum.dart @@ -1,6 +1,7 @@ // ignore_for_file: constant_identifier_names import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -44,11 +45,19 @@ extension MorphologicalCategoriesExtension on MorphologicalCategories { /// Convert string to enum static MorphologicalCategories? fromString(String category) { - return MorphologicalCategories.values.firstWhereOrNull( + final morph = MorphologicalCategories.values.firstWhereOrNull( (e) => e.toShortString() == category.toLowerCase().replaceAll(RegExp(r'[,\[\]]'), ''), ); + if (morph == null) { + ErrorHandler.logError( + e: "Missing morphological category", + s: StackTrace.current, + data: {"category": category}, + ); + } + return morph; } String getDisplayCopy(BuildContext context) { diff --git a/lib/pangea/enum/analytics/parts_of_speech_enum.dart b/lib/pangea/enum/analytics/parts_of_speech_enum.dart index 5348e938b..ea723fb7e 100644 --- a/lib/pangea/enum/analytics/parts_of_speech_enum.dart +++ b/lib/pangea/enum/analytics/parts_of_speech_enum.dart @@ -1,4 +1,5 @@ import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -31,9 +32,17 @@ extension GrammarCopyPOSExtension on GrammarCopyPOS { } GrammarCopyPOS? fromString(String categoryName) { - return GrammarCopyPOS.values.firstWhereOrNull( + final pos = GrammarCopyPOS.values.firstWhereOrNull( (pos) => pos.toShortString() == categoryName.toLowerCase(), ); + if (pos == null) { + ErrorHandler.logError( + e: "Missing part of speech", + s: StackTrace.current, + data: {"category": categoryName}, + ); + } + return pos; } String getDisplayCopy(BuildContext context) { diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index 86c36be30..05298d646 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -450,8 +450,7 @@ String? getGrammarCopy({ default: debugger(when: kDebugMode); ErrorHandler.logError( - e: Exception('Need to add copy for $key to intl_en.arb'), - m: 'Need to add copy for $key to intl_en.arb', + e: 'Need to add copy to intl_en.arb', data: { 'tag': key, 'context': context, From 94e52d8d9f7aebe6e949f9b9df3b398c4b563096 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 4 Nov 2024 13:42:26 -0500 Subject: [PATCH 10/13] added pagination to constructs list in analytics popup to speed up rendering --- .../analytics_summary/analytics_popup.dart | 93 ++++++++++++++++--- 1 file changed, 78 insertions(+), 15 deletions(-) diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart index 5eda9c97c..f3a60c0e7 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; @@ -65,21 +67,11 @@ class AnalyticsPopup extends StatelessWidget { final category = categoriesToUses[index]; return Column( children: [ - ExpansionTile( - title: Text( - category.value.first.constructType.getDisplayCopy( - category.key, - context, - ) ?? - category.key, - ), - children: category.value.map((constructUses) { - return ConstructUsesXPTile( - indicator: indicator, - constructsModel: constructsModel, - constructUses: constructUses, - ); - }).toList(), + ConstructUsesExpansionTile( + indicator: indicator, + constructsModel: constructsModel, + category: category.key, + constructUses: category.value, ), const Divider(height: 1), ], @@ -166,3 +158,74 @@ class ConstructUsesXPTile extends StatelessWidget { ); } } + +class ConstructUsesExpansionTile extends StatefulWidget { + final ProgressIndicatorEnum indicator; + final ConstructListModel constructsModel; + final String category; + final List constructUses; + + const ConstructUsesExpansionTile({ + required this.indicator, + required this.constructsModel, + required this.category, + required this.constructUses, + super.key, + }); + + @override + ConstructUsesExpansionTileState createState() => + ConstructUsesExpansionTileState(); +} + +class ConstructUsesExpansionTileState + extends State { + int _lastLoadedIndex = 50; + int get endIndex => min(_lastLoadedIndex, widget.constructUses.length); + + @override + Widget build(BuildContext context) { + final List xpTiles = widget.constructUses + .sublist(0, endIndex) + .map((constructUses) { + return ConstructUsesXPTile( + indicator: widget.indicator, + constructsModel: widget.constructsModel, + constructUses: constructUses, + ); + }) + .cast() + .toList(); + + if (widget.constructUses.length > _lastLoadedIndex) { + xpTiles.add( + Padding( + padding: const EdgeInsets.all(10), + child: TextButton( + child: Text(L10n.of(context)!.loadMore), + onPressed: () => setState(() => _lastLoadedIndex += 50), + ), + ), + ); + } + + return ExpansionTile( + title: Text( + widget.constructsModel.type == ConstructTypeEnum.morph + ? getGrammarCopy( + category: widget.category, + lemma: widget.constructUses.first.lemma, + context: context, + ) ?? + widget.category + : widget.category, + ), + children: xpTiles, + onExpansionChanged: (expanded) { + if (expanded) { + setState(() => _lastLoadedIndex = 50); + } + }, + ); + } +} From 28818e1fea3e6a53a7734f2052263e175f8d62e9 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 6 Nov 2024 16:44:02 -0500 Subject: [PATCH 11/13] don't group vocab --- .../widgets/chat_list/analytics_summary/analytics_popup.dart | 4 +++- .../analytics_summary/learning_progress_indicators.dart | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart index f3a60c0e7..56a593dcf 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -11,10 +11,12 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; class AnalyticsPopup extends StatelessWidget { final ProgressIndicatorEnum indicator; final ConstructListModel constructsModel; + final bool showGroups; const AnalyticsPopup({ required this.indicator, required this.constructsModel, + this.showGroups = true, super.key, }); @@ -49,7 +51,7 @@ class AnalyticsPopup extends StatelessWidget { if (hasNoData) { dialogContent = Center(child: Text(L10n.of(context)!.noDataFound)); - } else if (hasNoCategories) { + } else if (hasNoCategories || !showGroups) { dialogContent = ListView.builder( itemCount: constructsModel.constructListWithPoints.length, itemBuilder: (context, index) { diff --git a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart index 980ee1488..461177b3e 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart @@ -204,6 +204,8 @@ class LearningProgressIndicatorsState builder: (c) => AnalyticsPopup( indicator: indicator, constructsModel: model, + showGroups: indicator == + ProgressIndicatorEnum.morphsUsed, ), ); }, From 2dac558e1a8f3834d97a07cbb72cad9ebea6c2c7 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 7 Nov 2024 14:42:55 -0500 Subject: [PATCH 12/13] initial work on expanding popup to the side --- .../analytics_summary/analytics_popup.dart | 230 ------------------ .../analytics_popup/analytics_popup.dart | 136 +++++++++++ .../analytics_popup/analytics_xp_tile.dart | 61 +++++ .../learning_progress_indicators.dart | 2 +- 4 files changed, 198 insertions(+), 231 deletions(-) delete mode 100644 lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart create mode 100644 lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart create mode 100644 lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_xp_tile.dart diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart deleted file mode 100644 index e0f9c8bb9..000000000 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart +++ /dev/null @@ -1,230 +0,0 @@ -import 'dart:math'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; -import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; -import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; -import 'package:fluffychat/pangea/utils/get_grammar_copy.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class AnalyticsPopup extends StatelessWidget { - final ProgressIndicatorEnum indicator; - final ConstructListModel constructsModel; - final bool showGroups; - - const AnalyticsPopup({ - required this.indicator, - required this.constructsModel, - this.showGroups = true, - super.key, - }); - - List>> get categoriesToUses { - final entries = constructsModel.categoriesToUses.entries.toList(); - // Sort the list with custom logic - entries.sort((a, b) { - // Check if one of the keys is 'Other' - if (a.key == 'Other') return 1; - if (b.key == '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) { - Widget? dialogContent; - final bool hasNoData = constructsModel.constructListWithPoints.isEmpty; - final bool hasNoCategories = constructsModel.categoriesToUses.length == 1 && - constructsModel.categoriesToUses.keys.first == "Other"; - - if (hasNoData) { - dialogContent = Center(child: Text(L10n.of(context)!.noDataFound)); - } else if (hasNoCategories || !showGroups) { - dialogContent = ListView.builder( - itemCount: constructsModel.constructListWithPoints.length, - itemBuilder: (context, index) { - return ConstructUsesXPTile( - indicator: indicator, - constructsModel: constructsModel, - constructUses: constructsModel.constructListWithPoints[index], - ); - }, - ); - } else { - dialogContent = ListView.builder( - itemCount: categoriesToUses.length, - itemBuilder: (context, index) { - final category = categoriesToUses[index]; - return Column( - children: [ - ConstructUsesExpansionTile( - indicator: indicator, - constructsModel: constructsModel, - category: category.key, - constructUses: category.value, - ), - const Divider(height: 1), - ], - ); - }, - ); - } - - return Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 400, - maxHeight: 600, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(20.0), - child: Scaffold( - appBar: AppBar( - title: Text(indicator.tooltip(context)), - leading: IconButton( - icon: const Icon(Icons.close), - onPressed: Navigator.of(context).pop, - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(vertical: 20), - child: dialogContent, - ), - ), - ), - ), - ); - } -} - -class ConstructUsesXPTile extends StatelessWidget { - final ProgressIndicatorEnum indicator; - final ConstructListModel constructsModel; - final ConstructUses constructUses; - - const ConstructUsesXPTile({ - required this.indicator, - required this.constructsModel, - required this.constructUses, - super.key, - }); - - @override - Widget build(BuildContext context) { - return Tooltip( - message: "${constructUses.points} / ${constructsModel.maxXPPerLemma}", - child: ListTile( - onTap: () {}, - title: Text( - constructsModel.type == ConstructTypeEnum.morph - ? getGrammarCopy( - category: constructUses.category, - lemma: constructUses.lemma, - context: context, - ) ?? - constructUses.lemma - : constructUses.lemma, - ), - subtitle: Row( - children: [ - Expanded( - child: LinearProgressIndicator( - value: constructUses.points / constructsModel.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, - ), - ), - ); - } -} - -class ConstructUsesExpansionTile extends StatefulWidget { - final ProgressIndicatorEnum indicator; - final ConstructListModel constructsModel; - final String category; - final List constructUses; - - const ConstructUsesExpansionTile({ - required this.indicator, - required this.constructsModel, - required this.category, - required this.constructUses, - super.key, - }); - - @override - ConstructUsesExpansionTileState createState() => - ConstructUsesExpansionTileState(); -} - -class ConstructUsesExpansionTileState - extends State { - int _lastLoadedIndex = 50; - int get endIndex => min(_lastLoadedIndex, widget.constructUses.length); - - @override - Widget build(BuildContext context) { - final List xpTiles = widget.constructUses - .sublist(0, endIndex) - .map((constructUses) { - return ConstructUsesXPTile( - indicator: widget.indicator, - constructsModel: widget.constructsModel, - constructUses: constructUses, - ); - }) - .cast() - .toList(); - - if (widget.constructUses.length > _lastLoadedIndex) { - xpTiles.add( - Padding( - padding: const EdgeInsets.all(10), - child: TextButton( - child: Text(L10n.of(context)!.loadMore), - onPressed: () => setState(() => _lastLoadedIndex += 50), - ), - ), - ); - } - - return ExpansionTile( - title: Text( - widget.constructsModel.type?.getDisplayCopy( - widget.category, - context, - ) ?? - widget.category, - ), - children: xpTiles, - onExpansionChanged: (expanded) { - if (expanded) { - setState(() => _lastLoadedIndex = 50); - } - }, - ); - } -} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart new file mode 100644 index 000000000..2c561ad7a --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart @@ -0,0 +1,136 @@ +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_xp_tile.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class AnalyticsPopup extends StatefulWidget { + final ProgressIndicatorEnum indicator; + final ConstructListModel constructsModel; + final bool showGroups; + + const AnalyticsPopup({ + required this.indicator, + required this.constructsModel, + this.showGroups = true, + super.key, + }); + + @override + AnalyticsPopupState createState() => AnalyticsPopupState(); +} + +class AnalyticsPopupState extends State { + String? selectedCategory; + + List>> get categoriesToUses { + final entries = widget.constructsModel.categoriesToUses.entries.toList(); + // Sort the list with custom logic + entries.sort((a, b) { + // Check if one of the keys is 'Other' + if (a.key == 'Other') return 1; + if (b.key == '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; + } + + void setSelectedCategory(String? category) => setState(() { + selectedCategory = category; + }); + + @override + Widget build(BuildContext context) { + Widget? dialogContent; + final bool hasNoData = + widget.constructsModel.constructListWithPoints.isEmpty; + final bool hasNoCategories = + widget.constructsModel.categoriesToUses.length == 1 && + widget.constructsModel.categoriesToUses.keys.first == "Other"; + + if (selectedCategory != null) { + dialogContent = ListView.builder( + itemCount: + widget.constructsModel.categoriesToUses[selectedCategory]!.length, + itemBuilder: (context, index) { + final constructUses = + widget.constructsModel.categoriesToUses[selectedCategory]![index]; + return ConstructUsesXPTile(constructUses); + }, + ); + } else if (hasNoData) { + dialogContent = Center(child: Text(L10n.of(context)!.noDataFound)); + } else if (hasNoCategories || !widget.showGroups) { + dialogContent = ListView.builder( + itemCount: widget.constructsModel.constructListWithPoints.length, + itemBuilder: (context, index) { + final constructUses = + widget.constructsModel.constructListWithPoints[index]; + return ConstructUsesXPTile(constructUses); + }, + ); + } else { + dialogContent = ListView.builder( + itemCount: categoriesToUses.length, + itemBuilder: (context, index) { + final category = categoriesToUses[index]; + final copy = widget.constructsModel.type?.getDisplayCopy( + category.key, + context, + ) ?? + category.key; + return Column( + children: [ + ListTile( + title: Text(copy), + trailing: const Icon(Icons.chevron_right_outlined), + onTap: () => setSelectedCategory(category.key), + ), + const Divider(height: 1), + ], + ); + }, + ); + } + + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400, + maxHeight: 600, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20.0), + child: Scaffold( + appBar: AppBar( + title: Text(widget.indicator.tooltip(context)), + leading: IconButton( + icon: selectedCategory == null + ? const Icon(Icons.close) + : const Icon(Icons.chevron_left_outlined), + onPressed: selectedCategory == null + ? Navigator.of(context).pop + : () => setSelectedCategory(null), + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: dialogContent, + ), + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_xp_tile.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_xp_tile.dart new file mode 100644 index 000000000..b297418f7 --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_xp_tile.dart @@ -0,0 +1,61 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; +import 'package:fluffychat/pangea/utils/get_grammar_copy.dart'; +import 'package:flutter/material.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/widgets/chat_list/analytics_summary/learning_progress_indicators.dart b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart index 830bddca4..53e9ae172 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart @@ -9,7 +9,7 @@ import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar.dart'; import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_details.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart'; import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart'; import 'package:fluffychat/pangea/widgets/flag.dart'; import 'package:fluffychat/widgets/matrix.dart'; From ab5189a66a2e8be529155ccad0771102dfde3bbb Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 7 Nov 2024 16:29:29 -0500 Subject: [PATCH 13/13] added missing grammar copy and reduced some duplicate code --- lib/pangea/utils/get_grammar_copy.dart | 2 + .../analytics_popup/analytics_popup.dart | 56 ++++++++++++------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/pangea/utils/get_grammar_copy.dart b/lib/pangea/utils/get_grammar_copy.dart index 871cdd5a5..fa7178cf9 100644 --- a/lib/pangea/utils/get_grammar_copy.dart +++ b/lib/pangea/utils/get_grammar_copy.dart @@ -141,6 +141,8 @@ String? getGrammarCopy({ return L10n.of(context)!.grammarCopyPRONTYPEart; case 'grammarCopyPRONTYPEtot': return L10n.of(context)!.grammarCopyPRONTYPEtot; + case 'grammarCopyPRONTYPEneg': + return L10n.of(context)!.grammarCopyPRONTYPEneg; case 'grammarCopyPOLITEinfm': return L10n.of(context)!.grammarCopyPOLITEinfm; case 'grammarCopyADVTYPEtim': diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart index 2c561ad7a..16dd586eb 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart @@ -50,6 +50,13 @@ class AnalyticsPopupState extends State { selectedCategory = category; }); + String categoryCopy(category) => + widget.constructsModel.type?.getDisplayCopy( + category, + context, + ) ?? + category; + @override Widget build(BuildContext context) { Widget? dialogContent; @@ -60,40 +67,34 @@ class AnalyticsPopupState extends State { widget.constructsModel.categoriesToUses.keys.first == "Other"; if (selectedCategory != null) { - dialogContent = ListView.builder( - itemCount: - widget.constructsModel.categoriesToUses[selectedCategory]!.length, - itemBuilder: (context, index) { - final constructUses = - widget.constructsModel.categoriesToUses[selectedCategory]![index]; - return ConstructUsesXPTile(constructUses); - }, + dialogContent = Column( + children: [ + Text( + categoryCopy(selectedCategory), + style: const TextStyle(fontSize: 16), + ), + Expanded( + child: ConstructsTileList( + widget.constructsModel.categoriesToUses[selectedCategory]!, + ), + ), + ], ); } else if (hasNoData) { dialogContent = Center(child: Text(L10n.of(context)!.noDataFound)); } else if (hasNoCategories || !widget.showGroups) { - dialogContent = ListView.builder( - itemCount: widget.constructsModel.constructListWithPoints.length, - itemBuilder: (context, index) { - final constructUses = - widget.constructsModel.constructListWithPoints[index]; - return ConstructUsesXPTile(constructUses); - }, + dialogContent = ConstructsTileList( + widget.constructsModel.constructListWithPoints, ); } else { dialogContent = ListView.builder( itemCount: categoriesToUses.length, itemBuilder: (context, index) { final category = categoriesToUses[index]; - final copy = widget.constructsModel.type?.getDisplayCopy( - category.key, - context, - ) ?? - category.key; return Column( children: [ ListTile( - title: Text(copy), + title: Text(categoryCopy(category.key)), trailing: const Icon(Icons.chevron_right_outlined), onTap: () => setSelectedCategory(category.key), ), @@ -134,3 +135,16 @@ class AnalyticsPopupState extends State { ); } } + +class ConstructsTileList extends StatelessWidget { + final List constructs; + const ConstructsTileList(this.constructs, {super.key}); + + @override + Widget build(BuildContext context) { + return ListView.builder( + itemCount: constructs.length, + itemBuilder: (context, index) => ConstructUsesXPTile(constructs[index]), + ); + } +}