From d02acc988495f0e983bc7c72478018536e016cd1 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 3 Jul 2024 18:07:33 -0400 Subject: [PATCH 01/15] switching to token focus of saving constructs --- .../pangea_message_event.dart | 74 ++++++++++--------- lib/pangea/models/it_response_model.dart | 28 ++++--- lib/pangea/models/lemma.dart | 15 +--- lib/pangea/models/pangea_token_model.dart | 69 ++++++++--------- lib/pangea/repo/igc_repo.dart | 20 +++-- 5 files changed, 103 insertions(+), 103 deletions(-) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 334c0fa78..0dfaa149a 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -695,21 +695,25 @@ class PangeaMessageEvent { if (continuance.wasClicked) { //PTODO - account for end of flow score if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - uses.addAll( - _lemmasToVocabUses( - continuance.lemmas, - ConstructUseTypeEnum.incIt, - ), - ); + for (final token in continuance.tokens) { + uses.add( + _lemmaToVocabUse( + token.lemma, + ConstructUseTypeEnum.incIt, + ), + ); + } } } else { if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - uses.addAll( - _lemmasToVocabUses( - continuance.lemmas, - ConstructUseTypeEnum.ignIt, - ), - ); + for (final token in continuance.tokens) { + uses.add( + _lemmaToVocabUse( + token.lemma, + ConstructUseTypeEnum.ignIt, + ), + ); + } } } } @@ -729,13 +733,13 @@ class PangeaMessageEvent { // for each token, record whether selected in ga, ta, or wa for (final token in originalSent!.tokens!) { - uses.addAll(_getVocabUseForToken(token)); + uses.add(_getVocabUseForToken(token)); } return uses; } - /// Returns a list of [OneConstructUse] objects for the given [token] + /// Returns a [OneConstructUse] for the given [token] /// If there is no [originalSent] or [originalSent.choreo], the [token] is /// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language. /// Later on, we may want to consider putting it in some category of like 'pending' @@ -744,11 +748,11 @@ class PangeaMessageEvent { /// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch.choices], /// it is considered to be a [ConstructUseTypeEnum.corIt]. /// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa]. - List _getVocabUseForToken(PangeaToken token) { + OneConstructUse _getVocabUseForToken(PangeaToken token) { if (originalSent?.choreo == null) { final bool inUserL2 = originalSent?.langCode == l2Code; - return _lemmasToVocabUses( - token.lemmas, + return _lemmaToVocabUse( + token.lemma, inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, ); } @@ -763,42 +767,40 @@ class PangeaMessageEvent { step.text.contains(r.value), ) ?? false)) { - return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.ga); + return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.ga); } if (step.itStep != null) { final bool pickedThroughIT = step.itStep!.chosenContinuance?.text.contains(token.text.content) ?? false; if (pickedThroughIT) { - return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.corIt); + return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.corIt); //PTODO - check if added via custom input in IT flow } } } - return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.wa); + return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.wa); } /// Convert a list of [lemmas] into a list of vocab uses /// with the given [type] - List _lemmasToVocabUses( - List lemmas, + OneConstructUse _lemmaToVocabUse( + Lemma lemma, ConstructUseTypeEnum type, ) { final List uses = []; - for (final lemma in lemmas) { - if (lemma.saveVocab) { - uses.add( - OneConstructUse( - useType: type, - chatId: event.roomId!, - timeStamp: event.originServerTs, - lemma: lemma.text, - form: lemma.form, - msgId: event.eventId, - constructType: ConstructTypeEnum.vocab, - ), - ); - } + if (lemma.saveVocab) { + uses.add( + OneConstructUse( + useType: type, + chatId: event.roomId!, + timeStamp: event.originServerTs, + lemma: lemma.text, + form: lemma.form, + msgId: event.eventId, + constructType: ConstructTypeEnum.vocab, + ), + ); } return uses; } diff --git a/lib/pangea/models/it_response_model.dart b/lib/pangea/models/it_response_model.dart index 5fda36020..6adb4b4bc 100644 --- a/lib/pangea/models/it_response_model.dart +++ b/lib/pangea/models/it_response_model.dart @@ -2,11 +2,10 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/extensions/my_list_extension.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'lemma.dart'; - class ITResponseModel { String fullTextTranslation; List continuances; @@ -79,7 +78,7 @@ class Continuance { double probability; int level; String text; - List lemmas; + List tokens; /// saving this in a full json form String description; @@ -99,19 +98,18 @@ class Continuance { required this.inDictionary, required this.hasInfo, required this.gold, - required this.lemmas, + required this.tokens, }); factory Continuance.fromJson(Map json) { - final List lemmaInternal = - (json[ModelKey.lemma] != null && json[ModelKey.lemma] is Iterable) - ? (json[ModelKey.lemma] as Iterable) - .map( - (e) => Lemma.fromJson(e as Map), - ) - .toList() - .cast() - : []; + final List tokensInternal = (json[ModelKey.tokens] != null) + ? (json[ModelKey.tokens] as Iterable) + .map( + (e) => PangeaToken.fromJson(e as Map), + ) + .toList() + .cast() + : []; return Continuance( probability: json['probability'].toDouble(), level: json['level'], @@ -122,7 +120,7 @@ class Continuance { wasClicked: json['clkd'] ?? false, hasInfo: json['has_info'] ?? false, gold: json['gold'] ?? false, - lemmas: lemmaInternal, + tokens: tokensInternal, ); } @@ -132,7 +130,7 @@ class Continuance { data['level'] = level; data['text'] = text; data['clkd'] = wasClicked; - data[ModelKey.lemma] = lemmas.map((e) => e.toJson()).toList(); + data[ModelKey.tokens] = tokens.map((e) => e.toJson()).toList(); if (!condensed) { data['description'] = description; diff --git a/lib/pangea/models/lemma.dart b/lib/pangea/models/lemma.dart index 017a7ab88..1dc44c4b5 100644 --- a/lib/pangea/models/lemma.dart +++ b/lib/pangea/models/lemma.dart @@ -8,22 +8,13 @@ class Lemma { /// [saveVocab] true - whether to save the lemma to the user's vocabulary /// vocab that are not saved: emails, urls, numbers, punctuation, etc. + /// server handles this determination final bool saveVocab; - /// [pos] ex "v" - part of speech of the lemma - /// https://universaldependencies.org/u/pos/ - final String pos; - - /// [morph] ex {} - morphological features of the lemma - /// https://universaldependencies.org/u/feat/ - final Map morph; - Lemma({ required this.text, required this.saveVocab, required this.form, - this.pos = '', - this.morph = const {}, }); factory Lemma.fromJson(Map json) { @@ -31,8 +22,6 @@ class Lemma { text: json['text'], saveVocab: json['save_vocab'] ?? json['saveVocab'] ?? false, form: json["form"] ?? json['text'], - pos: json['pos'] ?? '', - morph: json['morph'] ?? '{}', ); } @@ -41,8 +30,6 @@ class Lemma { 'text': text, 'save_vocab': saveVocab, 'form': form, - 'pos': pos, - 'morph': morph, }; } diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 9dddd149b..7055c29fa 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -1,55 +1,58 @@ import 'dart:developer'; import 'package:flutter/foundation.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; import '../constants/model_keys.dart'; -import '../utils/error_handler.dart'; import 'lemma.dart'; class PangeaToken { PangeaTokenText text; - List lemmas; + Lemma lemma; + + /// [pos] ex "VERB" - part of speech of the token + /// https://universaldependencies.org/u/pos/ + final String pos; + + /// [morph] ex {} - morphological features of the token + /// https://universaldependencies.org/u/feat/ + final Map morph; PangeaToken({ required this.text, - required this.lemmas, + required this.lemma, + required this.pos, + required this.morph, }); - static getLemmas(String text, Iterable? json) { + static _getLemmas(String text, dynamic json) { if (json != null) { - return json - .map( - (e) => Lemma.fromJson(e as Map), - ) - .toList() - .cast(); + // July 24, 2024 - we're changing from a list to a single lemma and this is for backwards compatibility + // previously sent tokens have lists of lemmas + if (json is Iterable) { + return json + .map( + (e) => Lemma.fromJson(e as Map), + ) + .toList() + .cast(); + } else { + return Lemma.fromJson(json); + } } else { - return [Lemma(text: text, saveVocab: false, form: text)]; + // earlier still, we didn't have lemmas so this is for really old tokens + return Lemma(text: text, saveVocab: false, form: text); } } factory PangeaToken.fromJson(Map json) { - try { - final PangeaTokenText text = - PangeaTokenText.fromJson(json[_textKey] as Map); - return PangeaToken( - text: text, - lemmas: getLemmas(text.content, json[_lemmaKey]), - ); - } catch (err, s) { - debugger(when: kDebugMode); - Sentry.addBreadcrumb( - Breadcrumb( - message: "PangeaToken.fromJson error", - data: { - "json": json, - }, - ), - ); - ErrorHandler.logError(e: err, s: s); - rethrow; - } + final PangeaTokenText text = + PangeaTokenText.fromJson(json[_textKey] as Map); + return PangeaToken( + text: text, + lemma: _getLemmas(text.content, json[_lemmaKey]), + pos: json['pos'] ?? '', + morph: json['morph'] ?? '{}', + ); } static const String _textKey = "text"; @@ -57,7 +60,7 @@ class PangeaToken { Map toJson() => { _textKey: text.toJson(), - _lemmaKey: lemmas.map((e) => e.toJson()).toList(), + _lemmaKey: lemma.toJson(), }; int get end => text.offset + text.length; diff --git a/lib/pangea/repo/igc_repo.dart b/lib/pangea/repo/igc_repo.dart index d6271470a..e32f6cab7 100644 --- a/lib/pangea/repo/igc_repo.dart +++ b/lib/pangea/repo/igc_repo.dart @@ -47,23 +47,33 @@ class IgcRepo { tokens: [ PangeaToken( text: PangeaTokenText(content: "This", offset: 0, length: 4), - lemmas: [Lemma(form: "This", text: "this", saveVocab: true)], + lemma: Lemma(form: "This", text: "this", saveVocab: true), + pos: "DET", + morph: {}, ), PangeaToken( text: PangeaTokenText(content: "be", offset: 5, length: 2), - lemmas: [Lemma(form: "be", text: "be", saveVocab: true)], + lemma: Lemma(form: "be", text: "be", saveVocab: true), + pos: "VERB", + morph: {}, ), PangeaToken( text: PangeaTokenText(content: "a", offset: 8, length: 1), - lemmas: [], + lemma: Lemma(form: "a", text: "a", saveVocab: true), + pos: "DET", + morph: {}, ), PangeaToken( text: PangeaTokenText(content: "sample", offset: 10, length: 6), - lemmas: [], + lemma: Lemma(form: "sample", text: "sample", saveVocab: true), + pos: "NOUN", + morph: {}, ), PangeaToken( text: PangeaTokenText(content: "text", offset: 17, length: 4), - lemmas: [], + lemma: Lemma(form: "text", text: "text", saveVocab: true), + pos: "NOUN", + morph: {}, ), ], matches: [ From 77df13f5a9c4ef8e511390c9407ff66e9032383e Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 3 Jul 2024 18:10:49 -0400 Subject: [PATCH 02/15] --amend --- .../pangea_message_event.dart | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 0dfaa149a..530a7a547 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -687,7 +687,8 @@ class PangeaMessageEvent { for (final itStep in originalSent!.choreo!.itSteps) { for (final continuance in itStep.continuances) { - // this seems to always be false for continuances right now + final List tokensToSave = + continuance.tokens.where((t) => t.lemma.saveVocab).toList(); if (originalSent!.choreo!.finalMessage.contains(continuance.text)) { continue; @@ -695,7 +696,7 @@ class PangeaMessageEvent { if (continuance.wasClicked) { //PTODO - account for end of flow score if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - for (final token in continuance.tokens) { + for (final token in tokensToSave) { uses.add( _lemmaToVocabUse( token.lemma, @@ -706,7 +707,7 @@ class PangeaMessageEvent { } } else { if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - for (final token in continuance.tokens) { + for (final token in tokensToSave) { uses.add( _lemmaToVocabUse( token.lemma, @@ -732,7 +733,9 @@ class PangeaMessageEvent { } // for each token, record whether selected in ga, ta, or wa - for (final token in originalSent!.tokens!) { + for (final token in originalSent!.tokens! + .where((token) => token.lemma.saveVocab) + .toList()) { uses.add(_getVocabUseForToken(token)); } @@ -782,28 +785,19 @@ class PangeaMessageEvent { return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.wa); } - /// Convert a list of [lemmas] into a list of vocab uses - /// with the given [type] OneConstructUse _lemmaToVocabUse( Lemma lemma, ConstructUseTypeEnum type, - ) { - final List uses = []; - if (lemma.saveVocab) { - uses.add( - OneConstructUse( - useType: type, - chatId: event.roomId!, - timeStamp: event.originServerTs, - lemma: lemma.text, - form: lemma.form, - msgId: event.eventId, - constructType: ConstructTypeEnum.vocab, - ), + ) => + OneConstructUse( + useType: type, + chatId: event.roomId!, + timeStamp: event.originServerTs, + lemma: lemma.text, + form: lemma.form, + msgId: event.eventId, + constructType: ConstructTypeEnum.vocab, ); - } - return uses; - } /// get construct uses of type grammar for the message List get _grammarConstructUses { From bca1b87677aa62cce8d730cadd012b21c6d48dd7 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sun, 7 Jul 2024 19:31:29 -0400 Subject: [PATCH 03/15] added span display details to activity --- .../controllers/language_list_controller.dart | 1 - .../activity_display_instructions_enum.dart | 13 +++++ lib/pangea/models/pangea_token_model.dart | 16 ++++-- .../multiple_choice_activity_model.dart | 7 +++ .../practice_activity_model.dart | 56 +++++++++++++++++++ 5 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 lib/pangea/enum/activity_display_instructions_enum.dart diff --git a/lib/pangea/controllers/language_list_controller.dart b/lib/pangea/controllers/language_list_controller.dart index 31e4513fa..77f4ae9e2 100644 --- a/lib/pangea/controllers/language_list_controller.dart +++ b/lib/pangea/controllers/language_list_controller.dart @@ -93,7 +93,6 @@ class PangeaLanguage { } static LanguageModel byLangCode(String langCode) { - final list = _langList; for (final element in _langList) { if (element.langCode == langCode) return element; } diff --git a/lib/pangea/enum/activity_display_instructions_enum.dart b/lib/pangea/enum/activity_display_instructions_enum.dart new file mode 100644 index 000000000..9a96d669c --- /dev/null +++ b/lib/pangea/enum/activity_display_instructions_enum.dart @@ -0,0 +1,13 @@ +enum ActivityDisplayInstructionsEnum { highlight, hide } + +extension ActivityDisplayInstructionsEnumExt + on ActivityDisplayInstructionsEnum { + String get string { + switch (this) { + case ActivityDisplayInstructionsEnum.highlight: + return 'highlight'; + case ActivityDisplayInstructionsEnum.hide: + return 'hide'; + } + } +} diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 7055c29fa..608d5b9d1 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -24,17 +24,19 @@ class PangeaToken { required this.morph, }); - static _getLemmas(String text, dynamic json) { + static Lemma _getLemmas(String text, dynamic json) { if (json != null) { // July 24, 2024 - we're changing from a list to a single lemma and this is for backwards compatibility // previously sent tokens have lists of lemmas if (json is Iterable) { return json - .map( - (e) => Lemma.fromJson(e as Map), - ) - .toList() - .cast(); + .map( + (e) => Lemma.fromJson(e as Map), + ) + .toList() + .cast() + .firstOrNull ?? + Lemma(text: text, saveVocab: false, form: text); } else { return Lemma.fromJson(json); } @@ -61,6 +63,8 @@ class PangeaToken { Map toJson() => { _textKey: text.toJson(), _lemmaKey: lemma.toJson(), + 'pos': pos, + 'morph': morph, }; int get end => text.offset + text.length; diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index 68376d410..18302bd43 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -1,15 +1,18 @@ import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:flutter/material.dart'; class MultipleChoice { final String question; final List choices; final String answer; + final RelevantSpanDisplayDetails? spanDisplayDetails; MultipleChoice({ required this.question, required this.choices, required this.answer, + this.spanDisplayDetails, }); bool isCorrect(int index) => index == correctAnswerIndex; @@ -28,6 +31,9 @@ class MultipleChoice { question: json['question'] as String, choices: (json['choices'] as List).map((e) => e as String).toList(), answer: json['answer'] ?? json['correct_answer'] as String, + spanDisplayDetails: json['span_display_details'] != null + ? RelevantSpanDisplayDetails.fromJson(json['span_display_details']) + : null, ); } @@ -36,6 +42,7 @@ class MultipleChoice { 'question': question, 'choices': choices, 'answer': answer, + 'span_display_details': spanDisplayDetails, }; } } 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 fa3e25acf..645d550e5 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -1,5 +1,7 @@ import 'dart:developer'; +import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/enum/activity_display_instructions_enum.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; @@ -279,4 +281,58 @@ class PracticeActivityModel { 'free_response': freeResponse?.toJson(), }; } + + RelevantSpanDisplayDetails? getRelevantSpanDisplayDetails() { + switch (activityType) { + case ActivityTypeEnum.multipleChoice: + return multipleChoice?.spanDisplayDetails; + case ActivityTypeEnum.listening: + return null; + case ActivityTypeEnum.speaking: + return null; + case ActivityTypeEnum.freeResponse: + return null; + default: + debugger(when: kDebugMode); + return null; + } + } +} + +/// For those activities with a relevant span, this class will hold the details +/// of the span and how it should be displayed +/// e.g. hide the span for conjugation activities +class RelevantSpanDisplayDetails { + final int offset; + final int length; + final ActivityDisplayInstructionsEnum displayInstructions; + + RelevantSpanDisplayDetails({ + required this.offset, + required this.length, + required this.displayInstructions, + }); + + factory RelevantSpanDisplayDetails.fromJson(Map json) { + final ActivityDisplayInstructionsEnum? display = + ActivityDisplayInstructionsEnum.values.firstWhereOrNull( + (e) => e.string == json['display_instructions'], + ); + if (display == null) { + debugger(when: kDebugMode); + } + return RelevantSpanDisplayDetails( + offset: json['offset'] as int, + length: json['length'] as int, + displayInstructions: display ?? ActivityDisplayInstructionsEnum.hide, + ); + } + + Map toJson() { + return { + 'offset': offset, + 'length': length, + 'display_instructions': displayInstructions, + }; + } } From a5cdafcb659d0f03ffa1658ff09e1d40063fa4bc Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:24:13 -0400 Subject: [PATCH 04/15] Added null checks, error handling, and used non-null version of l10n --- lib/utils/error_reporter.dart | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/utils/error_reporter.dart b/lib/utils/error_reporter.dart index f3b3bfabd..76e39c193 100644 --- a/lib/utils/error_reporter.dart +++ b/lib/utils/error_reporter.dart @@ -9,15 +9,26 @@ class ErrorReporter { const ErrorReporter(this.context, [this.message]); void onErrorCallback(Object error, [StackTrace? stackTrace]) async { - Logs().e(message ?? 'Error caught', error, stackTrace); - // #Pangea - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - L10n.of(context)!.oopsSomethingWentWrong, - ), + Logs().e(message ?? 'Error caught', error, stackTrace); + // #Pangea + // Attempt to retrieve the L10n instance using the current context + final L10n? l10n = L10n.of(context); + + // Check if the L10n instance is null + if (l10n == null) { + // Log an error message saying that the localization object is null + Logs().e('Localization object is null, cannot show error message.'); + // Exits early to prevent further execution + return; + } + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + l10n.oopsSomethingWentWrong, // Use the non-null L10n instance to get the error message ), - ); + ), + ); +} // final text = '$error\n${stackTrace ?? ''}'; // await showAdaptiveDialog( // context: context, @@ -64,4 +75,4 @@ class ErrorReporter { // ); // Pangea# } -} + From 425b7ddcf12b85611d0edaf14f94f2509f5bfb88 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:37:39 -0400 Subject: [PATCH 05/15] oops formatting fix --- lib/utils/error_reporter.dart | 127 +++++++++++++++++----------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/lib/utils/error_reporter.dart b/lib/utils/error_reporter.dart index 76e39c193..d44b48dcb 100644 --- a/lib/utils/error_reporter.dart +++ b/lib/utils/error_reporter.dart @@ -9,70 +9,69 @@ class ErrorReporter { const ErrorReporter(this.context, [this.message]); void onErrorCallback(Object error, [StackTrace? stackTrace]) async { - Logs().e(message ?? 'Error caught', error, stackTrace); - // #Pangea - // Attempt to retrieve the L10n instance using the current context - final L10n? l10n = L10n.of(context); + Logs().e(message ?? 'Error caught', error, stackTrace); + // #Pangea + // Attempt to retrieve the L10n instance using the current context + final L10n? l10n = L10n.of(context); - // Check if the L10n instance is null - if (l10n == null) { - // Log an error message saying that the localization object is null - Logs().e('Localization object is null, cannot show error message.'); - // Exits early to prevent further execution - return; - } - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - l10n.oopsSomethingWentWrong, // Use the non-null L10n instance to get the error message + // Check if the L10n instance is null + if (l10n == null) { + // Log an error message saying that the localization object is null + Logs().e('Localization object is null, cannot show error message.'); + // Exits early to prevent further execution + return; + } + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + l10n.oopsSomethingWentWrong, // Use the non-null L10n instance to get the error message + ), ), - ), - ); -} - // final text = '$error\n${stackTrace ?? ''}'; - // await showAdaptiveDialog( - // context: context, - // builder: (context) => AlertDialog.adaptive( - // title: Text(L10n.of(context)!.reportErrorDescription), - // content: SizedBox( - // height: 256, - // width: 256, - // child: SingleChildScrollView( - // child: HighlightView( - // text, - // language: 'sh', - // theme: shadesOfPurpleTheme, - // ), - // ), - // ), - // actions: [ - // TextButton( - // onPressed: () => Navigator.of(context).pop(), - // child: Text(L10n.of(context)!.close), - // ), - // TextButton( - // onPressed: () => Clipboard.setData( - // ClipboardData(text: text), - // ), - // child: Text(L10n.of(context)!.copy), - // ), - // TextButton( - // onPressed: () => launchUrl( - // AppConfig.newIssueUrl.resolveUri( - // Uri( - // queryParameters: { - // 'template': 'bug_report.yaml', - // 'title': '[BUG]: ${message ?? error.toString()}', - // }, - // ), - // ), - // mode: LaunchMode.externalApplication, - // ), - // child: Text(L10n.of(context)!.report), - // ), - // ], - // ), - // ); - // Pangea# + ); } - + // final text = '$error\n${stackTrace ?? ''}'; + // await showAdaptiveDialog( + // context: context, + // builder: (context) => AlertDialog.adaptive( + // title: Text(L10n.of(context)!.reportErrorDescription), + // content: SizedBox( + // height: 256, + // width: 256, + // child: SingleChildScrollView( + // child: HighlightView( + // text, + // language: 'sh', + // theme: shadesOfPurpleTheme, + // ), + // ), + // ), + // actions: [ + // TextButton( + // onPressed: () => Navigator.of(context).pop(), + // child: Text(L10n.of(context)!.close), + // ), + // TextButton( + // onPressed: () => Clipboard.setData( + // ClipboardData(text: text), + // ), + // child: Text(L10n.of(context)!.copy), + // ), + // TextButton( + // onPressed: () => launchUrl( + // AppConfig.newIssueUrl.resolveUri( + // Uri( + // queryParameters: { + // 'template': 'bug_report.yaml', + // 'title': '[BUG]: ${message ?? error.toString()}', + // }, + // ), + // ), + // mode: LaunchMode.externalApplication, + // ), + // child: Text(L10n.of(context)!.report), + // ), + // ], + // ), + // ); + // Pangea# +} From 5494019be5407fa720dd54186ef87b5d6d1b252a Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Wed, 10 Jul 2024 16:47:22 -0400 Subject: [PATCH 06/15] set max char size for input field --- lib/pages/chat/input_bar.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index a02626978..04d1be9db 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -490,8 +490,10 @@ class InputBar extends StatelessWidget { keyboardType: keyboardType!, textInputAction: textInputAction, autofocus: autofocus!, + //setting max character count to 1000 + //after max, nothing else can be typed inputFormatters: [ - LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()), + LengthLimitingTextInputFormatter(1000), ], onSubmitted: (text) { // fix for library for now From 35434b09d1b389f8f4bcf7cd2d458f832aa96769 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:14:00 -0400 Subject: [PATCH 07/15] Add mounted check to prevent updates on unmounted widgets --- lib/pangea/widgets/chat/message_toolbar.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 8d2d66b7d..e10d637e0 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -194,6 +194,8 @@ class MessageToolbarState extends State { late StreamSubscription toolbarModeStream; void updateMode(MessageMode newMode) { + //Early exit from the function if the widget has been unmounted to prevent updates on an inactive widget. + if (!mounted) return; if (updatingMode) return; debugPrint("updating toolbar mode"); final bool subscribed = @@ -347,6 +349,7 @@ class MessageToolbarState extends State { Timer? timer; selectionStream = widget.textSelection.selectionStream.stream.listen((value) { + //talk about this timer?.cancel(); timer = Timer(const Duration(milliseconds: 500), () { if (value != null && value.isNotEmpty) { From 5f59a39c72c5f5378c44391daf3439e0df217003 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:16:37 -0400 Subject: [PATCH 08/15] removed comment --- lib/pangea/widgets/chat/message_toolbar.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index e10d637e0..f06b9d1b4 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -349,7 +349,6 @@ class MessageToolbarState extends State { Timer? timer; selectionStream = widget.textSelection.selectionStream.stream.listen((value) { - //talk about this timer?.cancel(); timer = Timer(const Duration(milliseconds: 500), () { if (value != null && value.isNotEmpty) { From bb32f584f4295c6f2b1baf0759017a6e3c9044f7 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:48:12 -0400 Subject: [PATCH 09/15] Fixed background for login view --- .../pages/p_user_age/p_user_age_view.dart | 51 +++++++------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/lib/pangea/pages/p_user_age/p_user_age_view.dart b/lib/pangea/pages/p_user_age/p_user_age_view.dart index 1438cf0fe..693099994 100644 --- a/lib/pangea/pages/p_user_age/p_user_age_view.dart +++ b/lib/pangea/pages/p_user_age/p_user_age_view.dart @@ -17,32 +17,25 @@ class PUserAgeView extends StatelessWidget { ), body: ListView( children: [ - Container( - margin: const EdgeInsets.only(top: 10), - padding: const EdgeInsets.all(15), - child: Text( - L10n.of(context)!.yourBirthdayPlease, - textAlign: TextAlign.justify, - style: const TextStyle( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox( - height: 10, - ), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - color: Theme.of(context) - .colorScheme - .onSecondaryContainer - .withAlpha(50), + color: Theme.of(context).colorScheme.onSecondaryContainer.withAlpha(50), ), child: Column( children: [ + Padding( + padding: const EdgeInsets.all(15), + child: Text( + L10n.of(context)!.yourBirthdayPlease, + textAlign: TextAlign.justify, + style: const TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.normal, + ), + ), + ), ListTile( title: Text( L10n.of(context)!.certifyAge(13), @@ -70,23 +63,16 @@ class PUserAgeView extends StatelessWidget { ], ), ), - const SizedBox( - height: 10, - ), - if (controller.error != null) - Padding( - padding: const EdgeInsets.all(12), - child: Text( - controller.error!, - style: const TextStyle(color: Colors.white), - ), - ), + const SizedBox(height: 20), Hero( tag: 'loginButton', child: Padding( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.symmetric(horizontal: 12), child: ElevatedButton( onPressed: controller.createUserInPangea, + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(50), + ), child: controller.loading ? const LinearProgressIndicator() : Text(L10n.of(context)!.getStarted), @@ -95,7 +81,6 @@ class PUserAgeView extends StatelessWidget { ), ], ), - // ), ); } } From 0ac4b664cee36b701f2b469d3d67cda908a5aef3 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 12 Jul 2024 17:03:00 -0400 Subject: [PATCH 10/15] changed from string to Map --- lib/pangea/models/pangea_token_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 608d5b9d1..ba0772740 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -53,7 +53,7 @@ class PangeaToken { text: text, lemma: _getLemmas(text.content, json[_lemmaKey]), pos: json['pos'] ?? '', - morph: json['morph'] ?? '{}', + morph: json['morph'] ?? {}, ); } From e6fa69df3910d9f77c671a4159e5dc753ed3634e Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:28:16 -0400 Subject: [PATCH 11/15] add back #pangea comment tags --- lib/pages/chat/input_bar.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 04d1be9db..9337b488a 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -490,10 +490,13 @@ class InputBar extends StatelessWidget { keyboardType: keyboardType!, textInputAction: textInputAction, autofocus: autofocus!, - //setting max character count to 1000 - //after max, nothing else can be typed inputFormatters: [ + //#Pangea + //LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()), + //setting max character count to 1000 + //after max, nothing else can be typed LengthLimitingTextInputFormatter(1000), + //Pangea# ], onSubmitted: (text) { // fix for library for now From c4ef72857888adc4842d2b09d6123e31f4c484c4 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 16 Jul 2024 09:06:58 -0400 Subject: [PATCH 12/15] client will consume lemma as single object but be capable of handling json lemma as list --- lib/pangea/models/pangea_token_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index ba0772740..089521e1a 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -62,7 +62,7 @@ class PangeaToken { Map toJson() => { _textKey: text.toJson(), - _lemmaKey: lemma.toJson(), + _lemmaKey: [lemma.toJson()], 'pos': pos, 'morph': morph, }; From 7e87c3154c3d1943a1cd59f0fddcea9ea174e8df Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 16 Jul 2024 09:38:54 -0400 Subject: [PATCH 13/15] fix for orange box error in learning settings, updated instructions to base their toggle status on matrix profile --- lib/pangea/enum/instructions_enum.dart | 18 +- .../settings_learning/settings_learning.dart | 25 +-- .../settings_learning_view.dart | 159 ++++++++---------- lib/pangea/utils/instructions.dart | 37 ++-- .../user_settings/country_picker_tile.dart | 36 ++-- .../user_settings/p_language_dialog.dart | 5 +- 6 files changed, 137 insertions(+), 143 deletions(-) diff --git a/lib/pangea/enum/instructions_enum.dart b/lib/pangea/enum/instructions_enum.dart index 376d004b5..4e12c12b8 100644 --- a/lib/pangea/enum/instructions_enum.dart +++ b/lib/pangea/enum/instructions_enum.dart @@ -1,4 +1,5 @@ import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -9,7 +10,7 @@ enum InstructionsEnum { tooltipInstructions, } -extension Copy on InstructionsEnum { +extension InstructionsEnumExtension on InstructionsEnum { String title(BuildContext context) { switch (this) { case InstructionsEnum.itInstructions: @@ -37,6 +38,21 @@ extension Copy on InstructionsEnum { : L10n.of(context)!.tooltipInstructionsBrowserBody; } } + + bool get toggledOff { + final instructionSettings = + MatrixState.pangeaController.userController.profile.instructionSettings; + switch (this) { + case InstructionsEnum.itInstructions: + return instructionSettings.showedItInstructions; + case InstructionsEnum.clickMessage: + return instructionSettings.showedClickMessage; + case InstructionsEnum.blurMeansTranslate: + return instructionSettings.showedBlurMeansTranslate; + case InstructionsEnum.tooltipInstructions: + return instructionSettings.showedTooltipInstructions; + } + } } enum InlineInstructions { diff --git a/lib/pangea/pages/settings_learning/settings_learning.dart b/lib/pangea/pages/settings_learning/settings_learning.dart index 03e5f635a..3e0a11e4c 100644 --- a/lib/pangea/pages/settings_learning/settings_learning.dart +++ b/lib/pangea/pages/settings_learning/settings_learning.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:country_picker/country_picker.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; @@ -17,25 +15,26 @@ class SettingsLearning extends StatefulWidget { } class SettingsLearningController extends State { - late StreamSubscription _userSubscription; PangeaController pangeaController = MatrixState.pangeaController; - Future changeLanguage() async { - await pLanguageDialog(context, () {}); - } - - Future setPublicProfile(bool isPublic) async { + setPublicProfile(bool isPublic) { pangeaController.userController.updateProfile((profile) { profile.userSettings.publicProfile = isPublic; return profile; }); + setState(() {}); } - Future changeCountry(Country country) async { - pangeaController.userController.updateProfile((profile) { + void changeLanguage() { + pLanguageDialog(context, () {}).then((_) => setState(() {})); + } + + void changeCountry(Country country) { + pangeaController.userController.updateProfile((Profile profile) { profile.userSettings.country = country.displayNameNoCountryCode; return profile; }); + setState(() {}); } void updateToolSetting(ToolSetting toolSetting, bool value) { @@ -71,12 +70,6 @@ class SettingsLearningController extends State { } } - @override - void dispose() { - super.dispose(); - _userSubscription.cancel(); - } - @override Widget build(BuildContext context) { return SettingsLearningView(this); diff --git a/lib/pangea/pages/settings_learning/settings_learning_view.dart b/lib/pangea/pages/settings_learning/settings_learning_view.dart index 5422ebbe5..4182ab2d6 100644 --- a/lib/pangea/pages/settings_learning/settings_learning_view.dart +++ b/lib/pangea/pages/settings_learning/settings_learning_view.dart @@ -1,15 +1,12 @@ +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/widgets/user_settings/country_picker_tile.dart'; import 'package:fluffychat/pangea/widgets/user_settings/language_tile.dart'; import 'package:fluffychat/pangea/widgets/user_settings/p_settings_switch_list_tile.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; - -import '../../../config/app_config.dart'; class SettingsLearningView extends StatelessWidget { final SettingsLearningController controller; @@ -17,97 +14,75 @@ class SettingsLearningView extends StatelessWidget { @override Widget build(BuildContext context) { - // rebuild this page each time a sync comes through with new account data - // this prevents having to call setState each time an individual setting is changed - return StreamBuilder( - stream: - controller.pangeaController.matrixState.client.onSync.stream.where( - (update) => update.accountData != null, + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + L10n.of(context)!.learningSettings, + ), ), - builder: (context, snapshot) { - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - L10n.of(context)!.learningSettings, - ), - ), - body: ListTileTheme( - iconColor: Theme.of(context).textTheme.bodyLarge!.color, - child: MaxWidthBody( - withScrolling: true, - child: Column( - children: [ - LanguageTile(controller), - CountryPickerTile(controller), - const SizedBox(height: 8), - const Divider(height: 1), - const SizedBox(height: 8), - if (controller.pangeaController.permissionsController - .isUser18()) - SwitchListTile.adaptive( - activeColor: AppConfig.activeToggleColor, - title: Text(L10n.of(context)!.publicProfileTitle), - subtitle: Text(L10n.of(context)!.publicProfileDesc), - value: - controller.pangeaController.userController.isPublic, - onChanged: (bool isPublicProfile) => - showFutureLoadingDialog( - context: context, - future: () => - controller.setPublicProfile(isPublicProfile), - onError: (err) => ErrorHandler.logError( - e: err, - s: StackTrace.current, - ), - ), - ), - ListTile( - subtitle: - Text(L10n.of(context)!.toggleToolSettingsDescription), - ), - for (final toolSetting in ToolSetting.values) - ProfileSettingsSwitchListTile.adaptive( - defaultValue: controller.getToolSetting(toolSetting), - title: toolSetting.toolName(context), - subtitle: toolSetting.toolDescription(context), - onChange: (bool value) => controller.updateToolSetting( - toolSetting, - value, - ), - ), - ProfileSettingsSwitchListTile.adaptive( - defaultValue: controller.pangeaController.userController - .profile.userSettings.itAutoPlay, - title: L10n.of(context)! - .interactiveTranslatorAutoPlaySliderHeader, - subtitle: - L10n.of(context)!.interactiveTranslatorAutoPlayDesc, - onChange: (bool value) => controller - .pangeaController.userController - .updateProfile((profile) { - profile.userSettings.itAutoPlay = value; - return profile; - }), - ), - ProfileSettingsSwitchListTile.adaptive( - defaultValue: controller.pangeaController.userController - .profile.userSettings.autoPlayMessages, - title: L10n.of(context)!.autoPlayTitle, - subtitle: L10n.of(context)!.autoPlayDesc, - onChange: (bool value) => controller - .pangeaController.userController - .updateProfile((profile) { - profile.userSettings.autoPlayMessages = value; - return profile; - }), - ), - ], + body: ListTileTheme( + iconColor: Theme.of(context).textTheme.bodyLarge!.color, + child: MaxWidthBody( + withScrolling: true, + child: Column( + children: [ + LanguageTile(controller), + CountryPickerTile(controller), + const SizedBox(height: 8), + const Divider(height: 1), + const SizedBox(height: 8), + if (controller.pangeaController.permissionsController.isUser18()) + SwitchListTile.adaptive( + activeColor: AppConfig.activeToggleColor, + title: Text(L10n.of(context)!.publicProfileTitle), + subtitle: Text(L10n.of(context)!.publicProfileDesc), + value: controller.pangeaController.userController.isPublic, + onChanged: (bool isPublicProfile) => + controller.setPublicProfile(isPublicProfile), + ), + ListTile( + subtitle: Text(L10n.of(context)!.toggleToolSettingsDescription), ), - ), + for (final toolSetting in ToolSetting.values) + ProfileSettingsSwitchListTile.adaptive( + defaultValue: controller.getToolSetting(toolSetting), + title: toolSetting.toolName(context), + subtitle: toolSetting.toolDescription(context), + onChange: (bool value) => controller.updateToolSetting( + toolSetting, + value, + ), + ), + ProfileSettingsSwitchListTile.adaptive( + defaultValue: controller.pangeaController.userController.profile + .userSettings.itAutoPlay, + title: + L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader, + subtitle: L10n.of(context)!.interactiveTranslatorAutoPlayDesc, + onChange: (bool value) => controller + .pangeaController.userController + .updateProfile((profile) { + profile.userSettings.itAutoPlay = value; + return profile; + }), + ), + ProfileSettingsSwitchListTile.adaptive( + defaultValue: controller.pangeaController.userController.profile + .userSettings.autoPlayMessages, + title: L10n.of(context)!.autoPlayTitle, + subtitle: L10n.of(context)!.autoPlayDesc, + onChange: (bool value) => controller + .pangeaController.userController + .updateProfile((profile) { + profile.userSettings.autoPlayMessages = value; + return profile; + }), + ), + ], ), - ); - }, + ), + ), ); } } diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index 948d6a1e4..165bfa460 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/utils/inline_tooltip.dart'; import 'package:flutter/material.dart'; @@ -24,8 +25,9 @@ class InstructionsController { final Map _instructionsShown = {}; /// Returns true if the user requested this popup not be shown again - bool? toggledOff(String key) => - _pangeaController.pStoreService.read(key.toString()); + bool? toggledOff(String key) => InstructionsEnum.values + .firstWhereOrNull((value) => value.toString() == key) + ?.toggledOff; InstructionsController(PangeaController pangeaController) { _pangeaController = pangeaController; @@ -33,19 +35,32 @@ class InstructionsController { /// Returns true if the instructions were closed /// or turned off by the user via the toggle switch - bool wereInstructionsTurnedOff(String key) => - toggledOff(key) ?? _instructionsClosed[key] ?? false; + bool wereInstructionsTurnedOff(String key) { + return toggledOff(key) ?? _instructionsClosed[key] ?? false; + } void turnOffInstruction(String key) => _instructionsClosed[key] = true; - Future updateEnableInstructions( + void updateEnableInstructions( String key, bool value, - ) async => - await _pangeaController.pStoreService.save( - key, - value, - ); + ) { + _pangeaController.userController.updateProfile((profile) { + if (key == InstructionsEnum.itInstructions.toString()) { + profile.instructionSettings.showedItInstructions = value; + } + if (key == InstructionsEnum.clickMessage.toString()) { + profile.instructionSettings.showedClickMessage = value; + } + if (key == InstructionsEnum.blurMeansTranslate.toString()) { + profile.instructionSettings.showedBlurMeansTranslate = value; + } + if (key == InstructionsEnum.tooltipInstructions.toString()) { + profile.instructionSettings.showedTooltipInstructions = value; + } + return profile; + }); + } /// Instruction Card gives users tips on /// how to use Pangea Chat's features @@ -170,7 +185,7 @@ class InstructionsToggleState extends State { widget.instructionsKey.toString(), ), onChanged: ((value) async { - await pangeaController.instructions.updateEnableInstructions( + pangeaController.instructions.updateEnableInstructions( widget.instructionsKey.toString(), value, ); diff --git a/lib/pangea/widgets/user_settings/country_picker_tile.dart b/lib/pangea/widgets/user_settings/country_picker_tile.dart index df292a837..c4441573d 100644 --- a/lib/pangea/widgets/user_settings/country_picker_tile.dart +++ b/lib/pangea/widgets/user_settings/country_picker_tile.dart @@ -1,14 +1,10 @@ -import 'dart:developer'; - import 'package:country_picker/country_picker.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; import 'package:fluffychat/pangea/utils/country_display.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; import '../../models/user_model.dart'; @@ -21,30 +17,26 @@ class CountryPickerTile extends StatelessWidget { @override Widget build(BuildContext context) { final Profile profile = pangeaController.userController.profile; + + final String displayName = CountryDisplayUtil.countryDisplayName( + profile.userSettings.country, + context, + ) ?? + ''; + + final String flag = CountryDisplayUtil.flagEmoji( + profile.userSettings.country, + ); + return ListTile( title: Text( - "${L10n.of(context)!.countryInformation}: ${CountryDisplayUtil.countryDisplayName( - profile.userSettings.country, - context, - ) ?? ''} ${CountryDisplayUtil.flagEmoji(profile.userSettings.country)}", + "${L10n.of(context)!.countryInformation}: $displayName $flag", ), trailing: const Icon(Icons.edit_outlined), onTap: () => showCountryPicker( context: context, - showPhoneCode: - false, // optional. Shows phone code before the country name. - onSelect: (Country country) async { - showFutureLoadingDialog( - context: context, - future: () async { - try { - learningController.changeCountry(country); - } catch (err) { - debugger(when: kDebugMode); - } - }, - ); - }, + showPhoneCode: false, + onSelect: learningController.changeCountry, ), ); } diff --git a/lib/pangea/widgets/user_settings/p_language_dialog.dart b/lib/pangea/widgets/user_settings/p_language_dialog.dart index 8635170a0..bfc85528b 100644 --- a/lib/pangea/widgets/user_settings/p_language_dialog.dart +++ b/lib/pangea/widgets/user_settings/p_language_dialog.dart @@ -15,7 +15,10 @@ import '../../../widgets/matrix.dart'; import 'p_language_dropdown.dart'; import 'p_question_container.dart'; -pLanguageDialog(BuildContext parentContext, Function callback) async { +Future pLanguageDialog( + BuildContext parentContext, + Function callback, +) async { final PangeaController pangeaController = MatrixState.pangeaController; //PTODO: if source language not set by user, default to languge from device settings final LanguageModel? userL1 = pangeaController.languageController.userL1; From 08faf399cc0a0932eeb3981365d8dee17a8cb8ea Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 16 Jul 2024 09:53:19 -0400 Subject: [PATCH 14/15] added fix for pangea profile toJson method --- lib/pangea/models/user_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index 972d7bbba..180422576 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -420,7 +420,7 @@ class PangeaProfileResponse { factory PangeaProfileResponse.fromJson(Map json) { return PangeaProfileResponse( - profile: PangeaProfile.fromJson(json), + profile: PangeaProfile.fromJson(json[ModelKey.userProfile]), access: json[ModelKey.userAccess], ); } From 057f07d2104d8d9e003644fb67d517a23dd29848 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 16 Jul 2024 10:04:34 -0400 Subject: [PATCH 15/15] removed debugger statement from my_analytics_controller update function - not an error state --- lib/pangea/controllers/my_analytics_controller.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 058bad359..12baeb689 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -229,11 +229,8 @@ class MyAnalyticsController { /// top level analytics sending function. Gather recent messages and activity records, /// convert them into the correct formats, and send them to the analytics room Future _updateAnalytics() async { - // if missing important info, don't send analytics - if (userL2 == null || _client.userID == null) { - debugger(when: kDebugMode); - return; - } + // if missing important info, don't send analytics. Could happen if user just signed up. + if (userL2 == null || _client.userID == null) return; // analytics room for the user and current target language final Room analyticsRoom = await _client.getMyAnalyticsRoom(userL2!);