From 558d8fdc503bd471e6c66602058e773aea9e092c Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 23 Jan 2026 10:30:26 -0500 Subject: [PATCH] fetch translation on activity target generation --- .../analytics_practice_page.dart | 10 -- .../analytics_practice_session_repo.dart | 19 +++- .../analytics_practice_view.dart | 107 ++++-------------- .../grammar_error_practice_generator.dart | 1 + .../message_activity_request.dart | 7 +- .../practice_activity_model.dart | 28 +++++ 6 files changed, 75 insertions(+), 97 deletions(-) diff --git a/lib/pangea/analytics_practice/analytics_practice_page.dart b/lib/pangea/analytics_practice/analytics_practice_page.dart index 4e6f57d51..7650a3a60 100644 --- a/lib/pangea/analytics_practice/analytics_practice_page.dart +++ b/lib/pangea/analytics_practice/analytics_practice_page.dart @@ -508,14 +508,4 @@ class AnalyticsPracticeState extends State @override Widget build(BuildContext context) => AnalyticsPracticeView(this); - - Future requestTranslation() async { - final request = activityTarget.value; - if (request?.grammarErrorInfo == null) { - throw L10n.of(context).oopsSomethingWentWrong; - } - - final event = request!.grammarErrorInfo!.event!; - return await event.requestRespresentationByL1(); - } } diff --git a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart index cf48314f9..3884dfc19 100644 --- a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart +++ b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart @@ -5,6 +5,7 @@ import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/analytics_practice/analytics_practice_constants.dart'; import 'package:fluffychat/pangea/analytics_practice/analytics_practice_session_model.dart'; import 'package:fluffychat/pangea/common/network/requests.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/events/models/pangea_token_model.dart'; @@ -256,6 +257,22 @@ class AnalyticsPracticeSessionRepo { // Skip if no valid tokens found for this grammar error if (choiceTokens.isEmpty) continue; + String? translation; + try { + translation = await event.requestRespresentationByL1(); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'context': 'AnalyticsPracticeSessionRepo._fetchErrors', + 'message': 'Failed to fetch translation for analytics practice', + 'event_id': event.eventId, + }, + ); + } + + if (translation == null) continue; targets.add( AnalyticsActivityTarget( target: PracticeTarget( @@ -267,7 +284,7 @@ class AnalyticsPracticeSessionRepo { choreo: choreo, stepIndex: i, eventID: event.eventId, - event: event, + translation: translation, ), ), ); diff --git a/lib/pangea/analytics_practice/analytics_practice_view.dart b/lib/pangea/analytics_practice/analytics_practice_view.dart index c7722e275..21cef073d 100644 --- a/lib/pangea/analytics_practice/analytics_practice_view.dart +++ b/lib/pangea/analytics_practice/analytics_practice_view.dart @@ -253,7 +253,7 @@ class _AnalyticsPracticeCenterContent extends StatelessWidget { key: ValueKey( '${activity.eventID}_${activity.errorOffset}_${activity.errorLength}', ), - controller: controller, + translation: activity.translation, ), ], ), @@ -557,11 +557,11 @@ class _ChoiceCard extends StatelessWidget { } class _GrammarErrorTranslationButton extends StatefulWidget { - final AnalyticsPracticeState controller; + final String translation; const _GrammarErrorTranslationButton({ super.key, - required this.controller, + required this.translation, }); @override @@ -571,19 +571,16 @@ class _GrammarErrorTranslationButton extends StatefulWidget { class _GrammarErrorTranslationButtonState extends State<_GrammarErrorTranslationButton> { - Future? _translationFuture; bool _showTranslation = false; void _toggleTranslation() { if (_showTranslation) { setState(() { _showTranslation = false; - _translationFuture = null; }); } else { setState(() { _showTranslation = true; - _translationFuture = widget.controller.requestTranslation(); }); } } @@ -599,83 +596,27 @@ class _GrammarErrorTranslationButtonState children: [ if (_showTranslation) Flexible( - child: FutureBuilder( - future: _translationFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Color.alphaBlend( - Colors.white.withAlpha(180), - ThemeData.dark().colorScheme.primary, - ), - borderRadius: BorderRadius.circular(16), - ), - child: const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), - ), - ); - } - - if (snapshot.hasError) { - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Color.alphaBlend( - Colors.white.withAlpha(180), - ThemeData.dark().colorScheme.primary, - ), - borderRadius: BorderRadius.circular(16), - ), - child: Text( - L10n.of(context).oopsSomethingWentWrong, - style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryFixed, - fontSize: AppConfig.fontSizeFactor * - AppConfig.messageFontSize, - ), - ), - ); - } - - if (snapshot.hasData) { - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - decoration: BoxDecoration( - color: Color.alphaBlend( - Colors.white.withAlpha(180), - ThemeData.dark().colorScheme.primary, - ), - borderRadius: BorderRadius.circular(16), - ), - child: Text( - snapshot.data!, - style: TextStyle( - color: Theme.of(context).colorScheme.onPrimaryFixed, - fontSize: AppConfig.fontSizeFactor * - AppConfig.messageFontSize, - ), - textAlign: TextAlign.center, - ), - ); - } - - return const SizedBox(); - }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: Color.alphaBlend( + Colors.white.withAlpha(180), + ThemeData.dark().colorScheme.primary, + ), + borderRadius: BorderRadius.circular(16), + ), + child: Text( + widget.translation, + style: TextStyle( + color: Theme.of(context).colorScheme.onPrimaryFixed, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + ), + textAlign: TextAlign.center, + ), ), ), if (!_showTranslation) diff --git a/lib/pangea/analytics_practice/grammar_error_practice_generator.dart b/lib/pangea/analytics_practice/grammar_error_practice_generator.dart index 30880ab50..854d1b66a 100644 --- a/lib/pangea/analytics_practice/grammar_error_practice_generator.dart +++ b/lib/pangea/analytics_practice/grammar_error_practice_generator.dart @@ -45,6 +45,7 @@ class GrammarErrorPracticeGenerator { errorOffset: igcMatch.offset, errorLength: igcMatch.length, eventID: eventID, + translation: req.grammarErrorInfo!.translation, ), ); } diff --git a/lib/pangea/practice_activities/message_activity_request.dart b/lib/pangea/practice_activities/message_activity_request.dart index d7788cb80..7452dd026 100644 --- a/lib/pangea/practice_activities/message_activity_request.dart +++ b/lib/pangea/practice_activities/message_activity_request.dart @@ -4,7 +4,6 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/choreographer/choreo_record_model.dart'; -import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart'; import 'package:fluffychat/pangea/practice_activities/practice_activity_model.dart'; @@ -46,13 +45,13 @@ class GrammarErrorRequestInfo { final ChoreoRecordModel choreo; final int stepIndex; final String eventID; - final PangeaMessageEvent? event; + final String translation; const GrammarErrorRequestInfo({ required this.choreo, required this.stepIndex, required this.eventID, - this.event, + required this.translation, }); Map toJson() { @@ -60,6 +59,7 @@ class GrammarErrorRequestInfo { 'choreo': choreo.toJson(), 'step_index': stepIndex, 'event_id': eventID, + 'translation': translation, }; } @@ -68,6 +68,7 @@ class GrammarErrorRequestInfo { choreo: ChoreoRecordModel.fromJson(json['choreo']), stepIndex: json['step_index'] as int, eventID: json['event_id'] as String, + translation: json['translation'] as String, ); } } diff --git a/lib/pangea/practice_activities/practice_activity_model.dart b/lib/pangea/practice_activities/practice_activity_model.dart index 602165b7c..c0531dcba 100644 --- a/lib/pangea/practice_activities/practice_activity_model.dart +++ b/lib/pangea/practice_activities/practice_activity_model.dart @@ -187,6 +187,21 @@ sealed class PracticeActivityModel { tokens: tokens, matchContent: matchContent!, ); + case ActivityTypeEnum.grammarError: + assert( + multipleChoiceContent != null, + "multipleChoiceContent is null in PracticeActivityModel.fromJson for grammarError", + ); + return GrammarErrorPracticeActivityModel( + langCode: langCode, + tokens: tokens, + multipleChoiceContent: multipleChoiceContent!, + text: json['text'] as String, + errorOffset: json['error_offset'] as int, + errorLength: json['error_length'] as int, + eventID: json['event_id'] as String, + translation: json['translation'] as String, + ); default: throw ("Unsupported activity type in PracticeActivityModel.fromJson: $type"); } @@ -358,6 +373,7 @@ class GrammarErrorPracticeActivityModel final int errorOffset; final int errorLength; final String eventID; + final String translation; GrammarErrorPracticeActivityModel({ required super.tokens, @@ -367,7 +383,19 @@ class GrammarErrorPracticeActivityModel required this.errorOffset, required this.errorLength, required this.eventID, + required this.translation, }); + + @override + Map toJson() { + final json = super.toJson(); + json['text'] = text; + json['error_offset'] = errorOffset; + json['error_length'] = errorLength; + json['event_id'] = eventID; + json['translation'] = translation; + return json; + } } class EmojiPracticeActivityModel extends MatchPracticeActivityModel {