From 7f844ff1a22cd39c7eaf1b8697eb090ccc02019d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 31 Oct 2024 11:42:44 -0400 Subject: [PATCH] decide whether to show points gain animation based on the origin of the point update --- lib/pages/chat/chat.dart | 1 + lib/pages/chat/chat_view.dart | 3 ++ .../controllers/it_controller.dart | 2 ++ lib/pangea/choreographer/widgets/it_bar.dart | 6 +++- .../controllers/get_analytics_controller.dart | 34 ++++++++++++++----- .../controllers/my_analytics_controller.dart | 24 ++++++++++--- .../widgets/animations/gain_points.dart | 9 +++-- .../learning_progress_indicators.dart | 7 ++-- lib/pangea/widgets/igc/span_card.dart | 7 +++- .../multiple_choice_activity.dart | 1 + .../practice_activity_card.dart | 5 ++- .../target_tokens_controller.dart | 12 +++---- .../word_focus_listening_activity.dart | 1 + 13 files changed, 84 insertions(+), 28 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index db5041623..203186116 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -691,6 +691,7 @@ class ChatController extends State metadata: metadata, )), ], + origin: AnalyticsUpdateOrigin.sendMessage, ), ); } diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 52d5ed351..e3df6a0e2 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -9,6 +9,7 @@ import 'package:fluffychat/pages/chat/pinned_events.dart'; import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/start_igc_button.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:fluffychat/pangea/widgets/chat/chat_floating_action_button.dart'; @@ -454,6 +455,8 @@ class ChatView extends StatelessWidget { gainColor: Theme.of(context) .colorScheme .onPrimary, + origin: AnalyticsUpdateOrigin + .sendMessage, ), const SizedBox(width: 100), ChatFloatingActionButton( diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index e30f30b3d..f04689ba0 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -315,6 +316,7 @@ class ITController { ignoredTokens ?? [], choreographer.roomId, ConstructUseTypeEnum.ignIt, + AnalyticsUpdateOrigin.it, ); Future.delayed( diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 9b81eb960..89f9c72ac 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -7,6 +7,7 @@ import 'package:fluffychat/pangea/choreographer/widgets/it_bar_buttons.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart'; import 'package:fluffychat/pangea/choreographer/widgets/translation_finished_flow.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -80,7 +81,9 @@ class ITBarState extends State { children: [ const Positioned( top: 60, - child: PointsGainedAnimation(), + child: PointsGainedAnimation( + origin: AnalyticsUpdateOrigin.it, + ), ), SingleChildScrollView( child: Column( @@ -372,6 +375,7 @@ class ITChoices extends StatelessWidget { continuance.level > 1 ? ConstructUseTypeEnum.incIt : ConstructUseTypeEnum.corIt, + AnalyticsUpdateOrigin.it, ); } controller.currentITStep!.continuances[index].wasClicked = true; diff --git a/lib/pangea/controllers/get_analytics_controller.dart b/lib/pangea/controllers/get_analytics_controller.dart index 26aa7234b..1f891ccd9 100644 --- a/lib/pangea/controllers/get_analytics_controller.dart +++ b/lib/pangea/controllers/get_analytics_controller.dart @@ -23,8 +23,8 @@ class GetAnalyticsController { late PangeaController _pangeaController; final List _cache = []; StreamSubscription? _analyticsUpdateSubscription; - CachedStreamController> analyticsStream = - CachedStreamController>(); + CachedStreamController analyticsStream = + CachedStreamController(); /// The previous XP points of the user, before the last update. /// Used for animating analytics updates. @@ -83,7 +83,7 @@ class GetAnalyticsController { _analyticsUpdateSubscription?.cancel(); _analyticsUpdateSubscription = null; _cache.clear(); - analyticsStream.add([]); + analyticsStream.add(AnalyticsStreamUpdate(constructs: [])); prevXP = null; } @@ -92,24 +92,30 @@ class GetAnalyticsController { if (analyticsUpdate.type == AnalyticsUpdateType.server) { await getConstructs(forceUpdate: true); } - updateAnalyticsStream(); + updateAnalyticsStream(origin: analyticsUpdate.origin); } - void updateAnalyticsStream() { + void updateAnalyticsStream({AnalyticsUpdateOrigin? origin}) { // if there are no construct uses, or if the last update in this // stream has the same length as this update, don't update the stream if (allConstructUses.isEmpty || - allConstructUses.length == analyticsStream.value?.length) { + allConstructUses.length == analyticsStream.value?.constructs.length) { return; } // set the previous XP to the currentXP - if (analyticsStream.value != null && analyticsStream.value!.isNotEmpty) { - prevXP = calcXP(analyticsStream.value!); + if (analyticsStream.value != null && + analyticsStream.value!.constructs.isNotEmpty) { + prevXP = calcXP(analyticsStream.value!.constructs); } // finally, add to the stream - analyticsStream.add(allConstructUses); + analyticsStream.add( + AnalyticsStreamUpdate( + constructs: allConstructUses, + origin: origin, + ), + ); } /// Calculates the user's xpPoints for their current L2, @@ -347,3 +353,13 @@ class AnalyticsCacheEntry { return _createdAt.isBefore(lastEventUpdated); } } + +class AnalyticsStreamUpdate { + final List constructs; + final AnalyticsUpdateOrigin? origin; + + AnalyticsStreamUpdate({ + required this.constructs, + this.origin, + }); +} diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 48dc67573..9c7523991 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -125,7 +125,7 @@ class MyAnalyticsController extends BaseController { _addLocalMessage(eventID, filtered).then( (_) { _clearDraftUses(roomID); - _decideWhetherToUpdateAnalyticsRoom(level); + _decideWhetherToUpdateAnalyticsRoom(level, data.origin); }, ); }); @@ -135,6 +135,7 @@ class MyAnalyticsController extends BaseController { List tokens, String roomID, ConstructUseTypeEnum useType, + AnalyticsUpdateOrigin origin, ) { final metadata = ConstructUseMetaData( roomId: roomID, @@ -178,7 +179,7 @@ class MyAnalyticsController extends BaseController { final level = _pangeaController.analytics.level; _addLocalMessage('draft$roomID', uses).then( - (_) => _decideWhetherToUpdateAnalyticsRoom(level), + (_) => _decideWhetherToUpdateAnalyticsRoom(level, origin), ); } @@ -218,7 +219,10 @@ class MyAnalyticsController extends BaseController { /// If the addition brought the total number of messages in the cache /// to the max, or if the addition triggered a level-up, update the analytics. /// Otherwise, add a local update to the alert stream. - void _decideWhetherToUpdateAnalyticsRoom(int prevLevel) { + void _decideWhetherToUpdateAnalyticsRoom( + int prevLevel, + AnalyticsUpdateOrigin? origin, + ) { // cancel the last timer that was set on message event and // reset it to fire after _minutesBeforeUpdate minutes _updateTimer?.cancel(); @@ -238,7 +242,7 @@ class MyAnalyticsController extends BaseController { newLevel > prevLevel ? sendLocalAnalyticsToAnalyticsRoom() : analyticsUpdateStream.add( - AnalyticsUpdate(AnalyticsUpdateType.local), + AnalyticsUpdate(AnalyticsUpdateType.local, origin: origin), ); } @@ -345,6 +349,7 @@ class MyAnalyticsController extends BaseController { class AnalyticsStream { final String eventId; final String roomId; + final AnalyticsUpdateOrigin? origin; final List constructs; @@ -352,12 +357,21 @@ class AnalyticsStream { required this.eventId, required this.roomId, required this.constructs, + this.origin, }); } +enum AnalyticsUpdateOrigin { + it, + igc, + sendMessage, + practiceActivity, +} + class AnalyticsUpdate { final AnalyticsUpdateType type; + final AnalyticsUpdateOrigin? origin; final bool isLogout; - AnalyticsUpdate(this.type, {this.isLogout = false}); + AnalyticsUpdate(this.type, {this.isLogout = false, this.origin}); } diff --git a/lib/pangea/widgets/animations/gain_points.dart b/lib/pangea/widgets/animations/gain_points.dart index 13ae324e7..d9d9a0111 100644 --- a/lib/pangea/widgets/animations/gain_points.dart +++ b/lib/pangea/widgets/animations/gain_points.dart @@ -1,6 +1,7 @@ import 'dart:async'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/controllers/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; @@ -8,8 +9,11 @@ import 'package:flutter/material.dart'; class PointsGainedAnimation extends StatefulWidget { final Color? gainColor; final Color? loseColor; + final AnalyticsUpdateOrigin origin; + const PointsGainedAnimation({ super.key, + required this.origin, this.gainColor, this.loseColor = Colors.red, }); @@ -69,7 +73,8 @@ class PointsGainedAnimationState extends State super.dispose(); } - void _showPointsGained(List constructs) { + void _showPointsGained(AnalyticsStreamUpdate update) { + if (update.origin != widget.origin) return; setState(() => _addedPoints = (_currentXP ?? 0) - (_prevXP ?? 0)); if (_prevXP != _currentXP) { _controller.reset(); 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 6695d2673..07a5aedb7 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 @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/controllers/get_analytics_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; @@ -37,7 +38,7 @@ class LearningProgressIndicatorsState /// A stream subscription to listen for updates to /// the analytics data, either locally or from events - StreamSubscription>? _analyticsUpdateSubscription; + StreamSubscription? _analyticsUpdateSubscription; /// Vocabulary constructs model ConstructListModel? words; @@ -65,11 +66,11 @@ class LearningProgressIndicatorsState void initState() { super.initState(); updateAnalyticsData( - _pangeaController.analytics.analyticsStream.value ?? [], + _pangeaController.analytics.analyticsStream.value?.constructs ?? [], ); _analyticsUpdateSubscription = _pangeaController .analytics.analyticsStream.stream - .listen(updateAnalyticsData); + .listen((update) => updateAnalyticsData(update.constructs)); } @override diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index ddfa43ba4..53bd4050d 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/enum/span_data_type.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart'; @@ -130,6 +131,7 @@ class SpanCardState extends State { selectedChoice!.isBestCorrection ? ConstructUseTypeEnum.corIGC : ConstructUseTypeEnum.incIGC, + AnalyticsUpdateOrigin.igc, ); } @@ -160,6 +162,7 @@ class SpanCardState extends State { ignoredTokens ?? [], widget.roomId, ConstructUseTypeEnum.ignIGC, + AnalyticsUpdateOrigin.igc, ); } @@ -226,7 +229,9 @@ class WordMatchContent extends StatelessWidget { children: [ const Positioned( top: 40, - child: PointsGainedAnimation(), + child: PointsGainedAnimation( + origin: AnalyticsUpdateOrigin.igc, + ), ), Column( children: [ diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart index e76021000..b427793a7 100644 --- a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart @@ -81,6 +81,7 @@ class MultipleChoiceActivityState extends State { widget.practiceCardController.currentActivity!, widget.practiceCardController.metadata, ), + origin: AnalyticsUpdateOrigin.practiceActivity, ), ); diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index dbb98de73..53644494d 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:developer'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; @@ -335,7 +336,9 @@ class PracticeActivityCardState extends State { children: [ // Main content const Positioned( - child: PointsGainedAnimation(), + child: PointsGainedAnimation( + origin: AnalyticsUpdateOrigin.practiceActivity, + ), ), if (activityWidget != null) Padding( diff --git a/lib/pangea/widgets/practice_activity/target_tokens_controller.dart b/lib/pangea/widgets/practice_activity/target_tokens_controller.dart index e358614f3..874a90a62 100644 --- a/lib/pangea/widgets/practice_activity/target_tokens_controller.dart +++ b/lib/pangea/widgets/practice_activity/target_tokens_controller.dart @@ -29,7 +29,9 @@ class TargetTokensController { _targetTokens = await _initialize(context, pangeaMessageEvent); await updateTokensWithConstructs( - MatrixState.pangeaController.analytics.analyticsStream.value ?? [], + MatrixState + .pangeaController.analytics.analyticsStream.value?.constructs ?? + [], context, pangeaMessageEvent, ); @@ -58,9 +60,8 @@ class TargetTokensController { return _targetTokens = []; } - return _targetTokens = tokens - .map((token) => token.emptyTokenWithXP) - .toList(); + return _targetTokens = + tokens.map((token) => token.emptyTokenWithXP).toList(); } Future updateTokensWithConstructs( @@ -76,9 +77,8 @@ class TargetTokensController { _targetTokens ??= await _initialize(context, pangeaMessageEvent); for (final token in _targetTokens!) { - // we don't need to do this for tokens that don't have saveVocab set to true - if (!token.token.lemma.saveVocab){ + if (!token.token.lemma.saveVocab) { continue; } diff --git a/lib/pangea/widgets/practice_activity/word_focus_listening_activity.dart b/lib/pangea/widgets/practice_activity/word_focus_listening_activity.dart index 8e22aced8..810074a76 100644 --- a/lib/pangea/widgets/practice_activity/word_focus_listening_activity.dart +++ b/lib/pangea/widgets/practice_activity/word_focus_listening_activity.dart @@ -79,6 +79,7 @@ class WordFocusListeningActivityState widget.practiceCardController.currentActivity!, widget.practiceCardController.metadata, ), + origin: AnalyticsUpdateOrigin.practiceActivity, ), ); setState(() {