From 96197138bafb040993d224ff50fc0838615e5b29 Mon Sep 17 00:00:00 2001 From: sienna-sterling <112006749+sienna-sterling@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:04:33 -0400 Subject: [PATCH] 1949-changing-it-feedback (#2088) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> Co-authored-by: ggurdin --- assets/l10n/intl_en.arb | 8 +- .../construct_use_type_enum.dart | 6 +- .../analytics_misc/gain_points_animation.dart | 3 +- .../utils/get_chat_list_item_subtitle.dart | 9 +- .../controllers/alternative_translator.dart | 150 ++++++++--------- lib/pangea/choreographer/widgets/it_bar.dart | 9 ++ .../widgets/it_feedback_stars.dart | 64 ++++++++ .../widgets/translation_finished_flow.dart | 153 +++++++++--------- lib/pangea/common/widgets/customized_svg.dart | 4 +- .../practice_activity_model.dart | 10 +- .../practice_selection.dart | 4 +- .../practice_selection_repo.dart | 6 +- .../practice_match_card.dart | 5 +- .../practice_match_item.dart | 5 +- .../toolbar/widgets/message_token_text.dart | 6 +- .../widgets/word_zoom/lemma_widget.dart | 6 +- 16 files changed, 271 insertions(+), 177 deletions(-) create mode 100644 lib/pangea/choreographer/widgets/it_feedback_stars.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 7d5f0b58a..9b093e70b 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4849,5 +4849,11 @@ "wordFocusListeningMultipleChoice": "Which audio matches the word?", "createActivity": "Create activity", "startChat": "Start a chat", - "translationProblem": "Translation problem" + "translationProblem": "Translation problem", + "perfectTranslation": "Perfect translation!", + "greatJobTranslation": "Great job with this translation!", + "goodJobTranslation": "Good work on this translation.", + "makingProgress": "You're making progress!", + "keepPracticing": "Keep practicing!", + "niceJob": "Nice job!" } \ No newline at end of file diff --git a/lib/pangea/analytics_misc/construct_use_type_enum.dart b/lib/pangea/analytics_misc/construct_use_type_enum.dart index d75a32aab..cad3d9047 100644 --- a/lib/pangea/analytics_misc/construct_use_type_enum.dart +++ b/lib/pangea/analytics_misc/construct_use_type_enum.dart @@ -1,8 +1,10 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; + import 'package:fluffychat/pangea/analytics_downloads/analytics_summary_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; enum ConstructUseTypeEnum { /// produced in chat by user, igc was run, and we've judged it to be a correct use diff --git a/lib/pangea/analytics_misc/gain_points_animation.dart b/lib/pangea/analytics_misc/gain_points_animation.dart index 3f34949b3..10fc8ed24 100644 --- a/lib/pangea/analytics_misc/gain_points_animation.dart +++ b/lib/pangea/analytics_misc/gain_points_animation.dart @@ -1,9 +1,10 @@ import 'dart:math'; +import 'package:flutter/material.dart'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/bot/utils/bot_style.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; class PointsGainedAnimation extends StatefulWidget { final int points; diff --git a/lib/pangea/chat_list/utils/get_chat_list_item_subtitle.dart b/lib/pangea/chat_list/utils/get_chat_list_item_subtitle.dart index 167916e7d..f1284dd3c 100644 --- a/lib/pangea/chat_list/utils/get_chat_list_item_subtitle.dart +++ b/lib/pangea/chat_list/utils/get_chat_list_item_subtitle.dart @@ -1,12 +1,13 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; + import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_token_text.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; - import '../../../utils/matrix_sdk_extensions/matrix_locals.dart'; class ChatListItemSubtitle extends StatelessWidget { diff --git a/lib/pangea/choreographer/controllers/alternative_translator.dart b/lib/pangea/choreographer/controllers/alternative_translator.dart index 1e69f1e1e..e26bc3aa1 100644 --- a/lib/pangea/choreographer/controllers/alternative_translator.dart +++ b/lib/pangea/choreographer/controllers/alternative_translator.dart @@ -3,10 +3,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:http/http.dart' as http; +import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; -import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_repo.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import '../repo/similarity_repo.dart'; class AlternativeTranslator { @@ -18,7 +19,6 @@ class AlternativeTranslator { FeedbackKey? translationFeedbackKey; List translations = []; SimilartyResponseModel? similarityResponse; - AlternativeTranslator(this.choreographer); void clear() { @@ -31,71 +31,49 @@ class AlternativeTranslator { similarityResponse = null; } + double get _percentCorrectChoices { + final totalSteps = choreographer.choreoRecord.itSteps.length; + if (totalSteps == 0) return 0.0; + final int correctFirstAttempts = choreographer.itController.completedITSteps + .where( + (step) => !step.continuances.any( + (c) => + c.level != ChoreoConstants.levelThresholdForGreen && + c.wasClicked, + ), + ) + .length; + final double percentage = (correctFirstAttempts / totalSteps) * 100; + return percentage; + } + + int get starRating { + final double percent = _percentCorrectChoices; + if (percent == 100) return 5; + if (percent >= 80) return 4; + if (percent >= 60) return 3; + if (percent >= 40) return 2; + if (percent > 0) return 1; + return 0; + } + Future setTranslationFeedback() async { try { choreographer.startLoading(); translationFeedbackKey = FeedbackKey.loadingPleaseWait; - showTranslationFeedback = true; - userTranslation = choreographer.currentText; - if (choreographer.itController.allCorrect) { + final double percentCorrect = _percentCorrectChoices; + + // Set feedback based on percentage + if (percentCorrect == 100) { translationFeedbackKey = FeedbackKey.allCorrect; - return; + } else if (percentCorrect >= 80) { + translationFeedbackKey = FeedbackKey.newWayAllGood; + } else { + translationFeedbackKey = FeedbackKey.othersAreBetter; } - - final String? goldRouteTranslation = - choreographer.itController.goldRouteTracker.fullTranslation; - - final FullTextTranslationResponseModel results = - await FullTextTranslationRepo.translate( - accessToken: choreographer.accessToken, - request: FullTextTranslationRequestModel( - text: choreographer.itController.sourceText!, - tgtLang: choreographer.l2LangCode!, - userL2: choreographer.l2LangCode!, - userL1: choreographer.l1LangCode!, - deepL: goldRouteTranslation == null, - ), - ); - translations = results.translations; - if (results.deepL != null || goldRouteTranslation != null) { - translations.insert(0, (results.deepL ?? goldRouteTranslation)!); - } - // final List altAndUser = [...results.translations]; - // if (results.deepL != null) { - // altAndUser.add(results.deepL!); - // } - // altAndUser.add(userTranslation); - - if (userTranslation?.toLowerCase() == - results.bestTranslation.toLowerCase()) { - translationFeedbackKey = FeedbackKey.allCorrect; - return; - } - - similarityResponse = await SimilarityRepo.get( - accessToken: choreographer.accessToken, - request: SimilarityRequestModel( - benchmark: results.bestTranslation, - toCompare: [userTranslation!], - ), - ); - - // if (similarityResponse! - // .userTranslationIsSameAsBotTranslation(userTranslation!)) { - // translationFeedbackKey = FeedbackKey.allCorrect; - // return; - // } - - // if (similarityResponse! - // .userTranslationIsDifferentButBetter(userTranslation!)) { - // translationFeedbackKey = FeedbackKey.newWayAllGood; - // return; - // } - showAlternativeTranslations = true; - translationFeedbackKey = FeedbackKey.othersAreBetter; } catch (err, stack) { if (err is! http.Response) { ErrorHandler.logError( @@ -119,36 +97,50 @@ class AlternativeTranslator { } } - String translationFeedback(BuildContext context) { + List get _selectedTokens => choreographer.choreoRecord.itSteps + .where((step) => step.chosenContinuance != null) + .map( + (step) => step.chosenContinuance!.tokens.where( + (token) => token.lemma.saveVocab, + ), + ) + .expand((element) => element) + .toList(); + + int countVocabularyWordsFromSteps() => + _selectedTokens.map((t) => t.lemma.text.toLowerCase()).toSet().length; + + int countGrammarConstructsFromSteps() => _selectedTokens + .map( + (t) => t.morph.entries.map( + (m) => "${m.key}:${m.value}".toLowerCase(), + ), + ) + .expand((m) => m) + .toSet() + .length; + + String getDefaultFeedback(BuildContext context) { + final l10n = L10n.of(context); switch (translationFeedbackKey) { case FeedbackKey.allCorrect: - return "Match: 100%\n${L10n.of(context).allCorrect}"; + return l10n.perfectTranslation; case FeedbackKey.newWayAllGood: - return "Match: 100%\n${L10n.of(context).newWayAllGood}"; + return l10n.greatJobTranslation; case FeedbackKey.othersAreBetter: - final num userScore = - (similarityResponse!.userScore(userTranslation!) * 100).round(); - final String displayScore = userScore.toString(); - if (userScore > 90) { - return "Match: $displayScore%\n${L10n.of(context).almostPerfect}"; + if (_percentCorrectChoices >= 60) { + return l10n.goodJobTranslation; } - if (userScore > 80) { - return "Match: $displayScore%\n${L10n.of(context).prettyGood}"; + if (_percentCorrectChoices >= 40) { + return l10n.makingProgress; } - return "Match: $displayScore%\n${L10n.of(context).othersAreBetter}"; - // case FeedbackKey.commonalityFeedback: - // final int count = controller.completedITSteps - // .where((element) => element.isCorrect) - // .toList() - // .length; - // final int total = controller.completedITSteps.length; - // return L10n.of(context).commonalityFeedback(count,total); + return l10n.keepPracticing; case FeedbackKey.loadingPleaseWait: - return L10n.of(context).letMeThink; + return l10n.letMeThink; case FeedbackKey.allDone: - return L10n.of(context).allDone; + return l10n.allDone; default: - return L10n.of(context).loadingPleaseWait; + return l10n.loadingPleaseWait; } } } diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 40a41a1f1..d03759f49 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -230,6 +230,15 @@ class ITBarState extends State with SingleTickerProviderStateMixin { : itController.isTranslationDone ? TranslationFeedback( controller: itController, + vocabCount: itController + .choreographer.altTranslator + .countVocabularyWordsFromSteps(), + grammarCount: itController + .choreographer.altTranslator + .countGrammarConstructsFromSteps(), + feedbackText: itController + .choreographer.altTranslator + .getDefaultFeedback(context), ) : ITChoices(controller: itController), ), diff --git a/lib/pangea/choreographer/widgets/it_feedback_stars.dart b/lib/pangea/choreographer/widgets/it_feedback_stars.dart new file mode 100644 index 000000000..c9f5a1b21 --- /dev/null +++ b/lib/pangea/choreographer/widgets/it_feedback_stars.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/choreographer/widgets/choice_animation.dart'; + +class FillingStars extends StatefulWidget { + final int rating; + + const FillingStars({ + super.key, + required this.rating, + }); + + @override + State createState() => _FillingStarsState(); +} + +class _FillingStarsState extends State { + final List _isFilledList = List.filled(5, false); + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => _animate()); + } + + Future _animate() async { + for (int i = 0; i < widget.rating; i++) { + await Future.delayed( + const Duration(milliseconds: choiceArrayAnimationDuration), () { + if (mounted) { + setState(() => _isFilledList[i] = true); + } + }); + } + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(5, (index) { + return AnimatedSwitcher( + duration: const Duration(milliseconds: choiceArrayAnimationDuration), + transitionBuilder: (Widget child, Animation animation) { + return ScaleTransition( + scale: animation, + child: child, + ); + }, + child: Icon( + _isFilledList[index] ? Icons.star_rounded : Icons.star_rounded, + key: ValueKey(_isFilledList[index]), + color: _isFilledList[index] + ? AppConfig.gold + : Theme.of(context).cardColor.withAlpha(180), + size: 32.0, + ), + ); + }), + ); + } +} diff --git a/lib/pangea/choreographer/widgets/translation_finished_flow.dart b/lib/pangea/choreographer/widgets/translation_finished_flow.dart index d7a8d273a..8e157ca93 100644 --- a/lib/pangea/choreographer/widgets/translation_finished_flow.dart +++ b/lib/pangea/choreographer/widgets/translation_finished_flow.dart @@ -1,94 +1,99 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:material_symbols_icons/symbols.dart'; + +import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_stars.dart'; import '../../bot/utils/bot_style.dart'; import '../../common/utils/error_handler.dart'; import '../controllers/it_controller.dart'; -import 'choice_array.dart'; class TranslationFeedback extends StatelessWidget { + final int vocabCount; + final int grammarCount; + final String feedbackText; + final ITController controller; - const TranslationFeedback({super.key, required this.controller}); + const TranslationFeedback({ + super.key, + required this.controller, + required this.vocabCount, + required this.grammarCount, + required this.feedbackText, + }); @override Widget build(BuildContext context) { - String feedbackText; - TextStyle? style; + final altTranslator = controller.choreographer.altTranslator; try { - feedbackText = - controller.choreographer.altTranslator.translationFeedback(context); - style = BotStyle.text(context); + return Column( + spacing: 16.0, + children: [ + FillingStars(rating: altTranslator.starRating), + if (vocabCount > 0 || grammarCount > 0) + Row( + mainAxisSize: MainAxisSize.min, + spacing: 16.0, + children: [ + if (vocabCount > 0) + Row( + spacing: 8.0, + children: [ + Icon( + Symbols.dictionary, + color: ProgressIndicatorEnum.wordsUsed.color(context), + size: 24, + ), + Text( + "+ $vocabCount", + style: TextStyle( + color: ProgressIndicatorEnum.wordsUsed.color(context), + fontWeight: FontWeight.bold, + ), + ), + ], + ), + if (grammarCount > 0) + Row( + spacing: 8.0, + children: [ + Icon( + Symbols.toys_and_games, + color: ProgressIndicatorEnum.morphsUsed.color(context), + size: 24, + ), + Text( + "+ $grammarCount", + style: TextStyle( + color: + ProgressIndicatorEnum.morphsUsed.color(context), + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ], + ) + else + Text( + feedbackText, + textAlign: TextAlign.center, + style: BotStyle.text(context), + ), + const SizedBox(height: 16.0), + ], + ); } catch (err, stack) { - feedbackText = "Nice job!"; - style = null; - debugPrint("error getting copy and styles"); + debugPrint("Error in TranslationFeedback: $err"); ErrorHandler.logError( e: err, s: stack, - data: { - "feedbackText": controller.choreographer.altTranslator - .translationFeedback(context), - }, + data: {}, ); + + // Fallback to a simple message if anything goes wrong + return Center(child: Text(L10n.of(context).niceJob)); } - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - if (controller.choreographer.altTranslator.showTranslationFeedback) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - children: [ - TextSpan( - text: "$feedbackText ", - style: style, - ), - ], - ), - ), - ), - const SizedBox(height: 6), - if (controller - .choreographer.altTranslator.showAlternativeTranslations) - AlternativeTranslations(controller: controller), - // if (!controller - // .choreographer.altTranslator.showAlternativeTranslations && - // !controller.choreographer.isFetching) - // ITRestartButton(controller: controller), - ], - ), - ); - } -} - -class AlternativeTranslations extends StatelessWidget { - const AlternativeTranslations({ - super.key, - required this.controller, - }); - - final ITController controller; - - @override - Widget build(BuildContext context) { - return ChoicesArray( - originalSpan: controller.sourceText ?? "dummy", - isLoading: - controller.choreographer.altTranslator.loadingAlternativeTranslations, - // choices: controller.choreographer.altTranslator.similarityResponse.scores - choices: [ - Choice(text: controller.choreographer.altTranslator.translations.first), - ], - // choices: controller.choreographer.altTranslator.translations, - onPressed: (String value, int index) { - controller.choreographer.onSelectAlternativeTranslation( - controller.choreographer.altTranslator.translations[index], - ); - }, - selectedChoiceIndex: null, - tts: null, - ); } } diff --git a/lib/pangea/common/widgets/customized_svg.dart b/lib/pangea/common/widgets/customized_svg.dart index fe2109c0b..5f7ec6718 100644 --- a/lib/pangea/common/widgets/customized_svg.dart +++ b/lib/pangea/common/widgets/customized_svg.dart @@ -1,9 +1,11 @@ -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:flutter/material.dart'; + import 'package:flutter_svg/flutter_svg.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart' as http; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; + class CustomizedSvg extends StatefulWidget { /// URL of the SVG file final String svgUrl; diff --git a/lib/pangea/practice_activities/practice_activity_model.dart b/lib/pangea/practice_activities/practice_activity_model.dart index 6d7a2645b..41637db28 100644 --- a/lib/pangea/practice_activities/practice_activity_model.dart +++ b/lib/pangea/practice_activities/practice_activity_model.dart @@ -1,6 +1,12 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; @@ -17,10 +23,6 @@ import 'package:fluffychat/pangea/practice_activities/practice_record.dart'; import 'package:fluffychat/pangea/practice_activities/practice_target.dart'; import 'package:fluffychat/pangea/practice_activities/relevant_span_display_details.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:sentry_flutter/sentry_flutter.dart'; class PracticeActivityModel { List targetTokens; diff --git a/lib/pangea/practice_activities/practice_selection.dart b/lib/pangea/practice_activities/practice_selection.dart index 5eefdc8b6..249608cf7 100644 --- a/lib/pangea/practice_activities/practice_selection.dart +++ b/lib/pangea/practice_activities/practice_selection.dart @@ -1,6 +1,9 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; + import 'package:collection/collection.dart'; + import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart'; @@ -9,7 +12,6 @@ import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart'; import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart'; import 'package:fluffychat/pangea/practice_activities/practice_target.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/foundation.dart'; class PracticeSelection { late String _userL2; diff --git a/lib/pangea/practice_activities/practice_selection_repo.dart b/lib/pangea/practice_activities/practice_selection_repo.dart index 35bb2a0fb..b80bbb7a3 100644 --- a/lib/pangea/practice_activities/practice_selection_repo.dart +++ b/lib/pangea/practice_activities/practice_selection_repo.dart @@ -1,7 +1,9 @@ +import 'package:flutter/material.dart'; + +import 'package:get_storage/get_storage.dart'; + import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/practice_activities/practice_selection.dart'; -import 'package:flutter/material.dart'; -import 'package:get_storage/get_storage.dart'; class PracticeSelectionRepo { static final GetStorage _storage = GetStorage('practice_selection_cache'); diff --git a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_card.dart b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_card.dart index 625ae8d7e..4c950ea93 100644 --- a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_card.dart +++ b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_card.dart @@ -1,5 +1,8 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_animation.dart'; import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart'; @@ -9,8 +12,6 @@ import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart'; import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_audio_card.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; class MatchActivityCard extends StatelessWidget { final PracticeActivityModel currentActivity; diff --git a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart index 773e4fc45..7cd1f0651 100644 --- a/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart +++ b/lib/pangea/toolbar/reading_assistance_input_row/practice_match_item.dart @@ -1,12 +1,13 @@ import 'dart:developer'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/practice_activities/practice_choice.dart'; import 'package:fluffychat/pangea/toolbar/controllers/tts_controller.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; class PracticeMatchItem extends StatefulWidget { const PracticeMatchItem({ diff --git a/lib/pangea/toolbar/widgets/message_token_text.dart b/lib/pangea/toolbar/widgets/message_token_text.dart index 72ec9cc50..4ad28f12f 100644 --- a/lib/pangea/toolbar/widgets/message_token_text.dart +++ b/lib/pangea/toolbar/widgets/message_token_text.dart @@ -1,4 +1,8 @@ +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/common/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; @@ -11,8 +15,6 @@ import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_linkify/flutter_linkify.dart'; /// Question - does this need to be stateful or does this work? /// Need to test. diff --git a/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart b/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart index 77a9d91bf..706a8bf8e 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/lemma_widget.dart @@ -1,3 +1,7 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; + import 'package:fluffychat/pangea/common/constants/model_keys.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; @@ -9,8 +13,6 @@ import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart'; import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart'; import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/word_audio_button.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; class LemmaWidget extends StatefulWidget { final PangeaToken token;