Merge pull request #881 from pangeachat/show-gained-points-in-one-place

decide whether to show points gain animation based on the origin of t…
pull/1476/head
ggurdin 1 year ago committed by GitHub
commit 4dfc080b03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -691,6 +691,7 @@ class ChatController extends State<ChatPageWithRoom>
metadata: metadata, metadata: metadata,
)), )),
], ],
origin: AnalyticsUpdateOrigin.sendMessage,
), ),
); );
} }

@ -9,6 +9,7 @@ import 'package:fluffychat/pages/chat/pinned_events.dart';
import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pages/chat/reply_display.dart';
import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart';
import 'package:fluffychat/pangea/choreographer/widgets/start_igc_button.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/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:fluffychat/pangea/widgets/animations/gain_points.dart';
import 'package:fluffychat/pangea/widgets/chat/chat_floating_action_button.dart'; import 'package:fluffychat/pangea/widgets/chat/chat_floating_action_button.dart';
@ -454,6 +455,8 @@ class ChatView extends StatelessWidget {
gainColor: Theme.of(context) gainColor: Theme.of(context)
.colorScheme .colorScheme
.onPrimary, .onPrimary,
origin: AnalyticsUpdateOrigin
.sendMessage,
), ),
const SizedBox(width: 100), const SizedBox(width: 100),
ChatFloatingActionButton( ChatFloatingActionButton(

@ -3,6 +3,7 @@ import 'dart:developer';
import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart';
import 'package:fluffychat/pangea/constants/choreo_constants.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/construct_use_type_enum.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart';
@ -315,6 +316,7 @@ class ITController {
ignoredTokens ?? [], ignoredTokens ?? [],
choreographer.roomId, choreographer.roomId,
ConstructUseTypeEnum.ignIt, ConstructUseTypeEnum.ignIt,
AnalyticsUpdateOrigin.it,
); );
Future.delayed( Future.delayed(

@ -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/it_feedback_card.dart';
import 'package:fluffychat/pangea/choreographer/widgets/translation_finished_flow.dart'; import 'package:fluffychat/pangea/choreographer/widgets/translation_finished_flow.dart';
import 'package:fluffychat/pangea/constants/choreo_constants.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/construct_use_type_enum.dart';
import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart';
@ -80,7 +81,9 @@ class ITBarState extends State<ITBar> {
children: [ children: [
const Positioned( const Positioned(
top: 60, top: 60,
child: PointsGainedAnimation(), child: PointsGainedAnimation(
origin: AnalyticsUpdateOrigin.it,
),
), ),
SingleChildScrollView( SingleChildScrollView(
child: Column( child: Column(
@ -372,6 +375,7 @@ class ITChoices extends StatelessWidget {
continuance.level > 1 continuance.level > 1
? ConstructUseTypeEnum.incIt ? ConstructUseTypeEnum.incIt
: ConstructUseTypeEnum.corIt, : ConstructUseTypeEnum.corIt,
AnalyticsUpdateOrigin.it,
); );
} }
controller.currentITStep!.continuances[index].wasClicked = true; controller.currentITStep!.continuances[index].wasClicked = true;

@ -23,8 +23,8 @@ class GetAnalyticsController {
late PangeaController _pangeaController; late PangeaController _pangeaController;
final List<AnalyticsCacheEntry> _cache = []; final List<AnalyticsCacheEntry> _cache = [];
StreamSubscription<AnalyticsUpdate>? _analyticsUpdateSubscription; StreamSubscription<AnalyticsUpdate>? _analyticsUpdateSubscription;
CachedStreamController<List<OneConstructUse>> analyticsStream = CachedStreamController<AnalyticsStreamUpdate> analyticsStream =
CachedStreamController<List<OneConstructUse>>(); CachedStreamController<AnalyticsStreamUpdate>();
/// The previous XP points of the user, before the last update. /// The previous XP points of the user, before the last update.
/// Used for animating analytics updates. /// Used for animating analytics updates.
@ -83,7 +83,7 @@ class GetAnalyticsController {
_analyticsUpdateSubscription?.cancel(); _analyticsUpdateSubscription?.cancel();
_analyticsUpdateSubscription = null; _analyticsUpdateSubscription = null;
_cache.clear(); _cache.clear();
analyticsStream.add([]); analyticsStream.add(AnalyticsStreamUpdate(constructs: []));
prevXP = null; prevXP = null;
} }
@ -92,24 +92,30 @@ class GetAnalyticsController {
if (analyticsUpdate.type == AnalyticsUpdateType.server) { if (analyticsUpdate.type == AnalyticsUpdateType.server) {
await getConstructs(forceUpdate: true); 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 // 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 // stream has the same length as this update, don't update the stream
if (allConstructUses.isEmpty || if (allConstructUses.isEmpty ||
allConstructUses.length == analyticsStream.value?.length) { allConstructUses.length == analyticsStream.value?.constructs.length) {
return; return;
} }
// set the previous XP to the currentXP // set the previous XP to the currentXP
if (analyticsStream.value != null && analyticsStream.value!.isNotEmpty) { if (analyticsStream.value != null &&
prevXP = calcXP(analyticsStream.value!); analyticsStream.value!.constructs.isNotEmpty) {
prevXP = calcXP(analyticsStream.value!.constructs);
} }
// finally, add to the stream // finally, add to the stream
analyticsStream.add(allConstructUses); analyticsStream.add(
AnalyticsStreamUpdate(
constructs: allConstructUses,
origin: origin,
),
);
} }
/// Calculates the user's xpPoints for their current L2, /// Calculates the user's xpPoints for their current L2,
@ -347,3 +353,13 @@ class AnalyticsCacheEntry {
return _createdAt.isBefore(lastEventUpdated); return _createdAt.isBefore(lastEventUpdated);
} }
} }
class AnalyticsStreamUpdate {
final List<OneConstructUse> constructs;
final AnalyticsUpdateOrigin? origin;
AnalyticsStreamUpdate({
required this.constructs,
this.origin,
});
}

@ -125,7 +125,7 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
_addLocalMessage(eventID, filtered).then( _addLocalMessage(eventID, filtered).then(
(_) { (_) {
_clearDraftUses(roomID); _clearDraftUses(roomID);
_decideWhetherToUpdateAnalyticsRoom(level); _decideWhetherToUpdateAnalyticsRoom(level, data.origin);
}, },
); );
}); });
@ -135,6 +135,7 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
List<PangeaToken> tokens, List<PangeaToken> tokens,
String roomID, String roomID,
ConstructUseTypeEnum useType, ConstructUseTypeEnum useType,
AnalyticsUpdateOrigin origin,
) { ) {
final metadata = ConstructUseMetaData( final metadata = ConstructUseMetaData(
roomId: roomID, roomId: roomID,
@ -178,7 +179,7 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
final level = _pangeaController.analytics.level; final level = _pangeaController.analytics.level;
_addLocalMessage('draft$roomID', uses).then( _addLocalMessage('draft$roomID', uses).then(
(_) => _decideWhetherToUpdateAnalyticsRoom(level), (_) => _decideWhetherToUpdateAnalyticsRoom(level, origin),
); );
} }
@ -218,7 +219,10 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
/// If the addition brought the total number of messages in the cache /// 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. /// to the max, or if the addition triggered a level-up, update the analytics.
/// Otherwise, add a local update to the alert stream. /// 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 // cancel the last timer that was set on message event and
// reset it to fire after _minutesBeforeUpdate minutes // reset it to fire after _minutesBeforeUpdate minutes
_updateTimer?.cancel(); _updateTimer?.cancel();
@ -238,7 +242,7 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
newLevel > prevLevel newLevel > prevLevel
? sendLocalAnalyticsToAnalyticsRoom() ? sendLocalAnalyticsToAnalyticsRoom()
: analyticsUpdateStream.add( : analyticsUpdateStream.add(
AnalyticsUpdate(AnalyticsUpdateType.local), AnalyticsUpdate(AnalyticsUpdateType.local, origin: origin),
); );
} }
@ -345,6 +349,7 @@ class MyAnalyticsController extends BaseController<AnalyticsStream> {
class AnalyticsStream { class AnalyticsStream {
final String eventId; final String eventId;
final String roomId; final String roomId;
final AnalyticsUpdateOrigin? origin;
final List<OneConstructUse> constructs; final List<OneConstructUse> constructs;
@ -352,12 +357,21 @@ class AnalyticsStream {
required this.eventId, required this.eventId,
required this.roomId, required this.roomId,
required this.constructs, required this.constructs,
this.origin,
}); });
} }
enum AnalyticsUpdateOrigin {
it,
igc,
sendMessage,
practiceActivity,
}
class AnalyticsUpdate { class AnalyticsUpdate {
final AnalyticsUpdateType type; final AnalyticsUpdateType type;
final AnalyticsUpdateOrigin? origin;
final bool isLogout; final bool isLogout;
AnalyticsUpdate(this.type, {this.isLogout = false}); AnalyticsUpdate(this.type, {this.isLogout = false, this.origin});
} }

@ -1,6 +1,7 @@
import 'dart:async'; 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/pangea/utils/bot_style.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -8,8 +9,11 @@ import 'package:flutter/material.dart';
class PointsGainedAnimation extends StatefulWidget { class PointsGainedAnimation extends StatefulWidget {
final Color? gainColor; final Color? gainColor;
final Color? loseColor; final Color? loseColor;
final AnalyticsUpdateOrigin origin;
const PointsGainedAnimation({ const PointsGainedAnimation({
super.key, super.key,
required this.origin,
this.gainColor, this.gainColor,
this.loseColor = Colors.red, this.loseColor = Colors.red,
}); });
@ -69,7 +73,8 @@ class PointsGainedAnimationState extends State<PointsGainedAnimation>
super.dispose(); super.dispose();
} }
void _showPointsGained(List<OneConstructUse> constructs) { void _showPointsGained(AnalyticsStreamUpdate update) {
if (update.origin != widget.origin) return;
setState(() => _addedPoints = (_currentXP ?? 0) - (_prevXP ?? 0)); setState(() => _addedPoints = (_currentXP ?? 0) - (_prevXP ?? 0));
if (_prevXP != _currentXP) { if (_prevXP != _currentXP) {
_controller.reset(); _controller.reset();

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:fluffychat/config/themes.dart'; 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/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
import 'package:fluffychat/pangea/enum/progress_indicators_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 /// A stream subscription to listen for updates to
/// the analytics data, either locally or from events /// the analytics data, either locally or from events
StreamSubscription<List<OneConstructUse>>? _analyticsUpdateSubscription; StreamSubscription<AnalyticsStreamUpdate>? _analyticsUpdateSubscription;
/// Vocabulary constructs model /// Vocabulary constructs model
ConstructListModel? words; ConstructListModel? words;
@ -65,11 +66,11 @@ class LearningProgressIndicatorsState
void initState() { void initState() {
super.initState(); super.initState();
updateAnalyticsData( updateAnalyticsData(
_pangeaController.analytics.analyticsStream.value ?? [], _pangeaController.analytics.analyticsStream.value?.constructs ?? [],
); );
_analyticsUpdateSubscription = _pangeaController _analyticsUpdateSubscription = _pangeaController
.analytics.analyticsStream.stream .analytics.analyticsStream.stream
.listen(updateAnalyticsData); .listen((update) => updateAnalyticsData(update.constructs));
} }
@override @override

@ -1,6 +1,7 @@
import 'dart:developer'; import 'dart:developer';
import 'package:fluffychat/config/app_config.dart'; 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/construct_use_type_enum.dart';
import 'package:fluffychat/pangea/enum/span_data_type.dart'; import 'package:fluffychat/pangea/enum/span_data_type.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart';
@ -130,6 +131,7 @@ class SpanCardState extends State<SpanCard> {
selectedChoice!.isBestCorrection selectedChoice!.isBestCorrection
? ConstructUseTypeEnum.corIGC ? ConstructUseTypeEnum.corIGC
: ConstructUseTypeEnum.incIGC, : ConstructUseTypeEnum.incIGC,
AnalyticsUpdateOrigin.igc,
); );
} }
@ -160,6 +162,7 @@ class SpanCardState extends State<SpanCard> {
ignoredTokens ?? [], ignoredTokens ?? [],
widget.roomId, widget.roomId,
ConstructUseTypeEnum.ignIGC, ConstructUseTypeEnum.ignIGC,
AnalyticsUpdateOrigin.igc,
); );
} }
@ -226,7 +229,9 @@ class WordMatchContent extends StatelessWidget {
children: [ children: [
const Positioned( const Positioned(
top: 40, top: 40,
child: PointsGainedAnimation(), child: PointsGainedAnimation(
origin: AnalyticsUpdateOrigin.igc,
),
), ),
Column( Column(
children: [ children: [

@ -81,6 +81,7 @@ class MultipleChoiceActivityState extends State<MultipleChoiceActivity> {
widget.practiceCardController.currentActivity!, widget.practiceCardController.currentActivity!,
widget.practiceCardController.metadata, widget.practiceCardController.metadata,
), ),
origin: AnalyticsUpdateOrigin.practiceActivity,
), ),
); );

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
@ -335,7 +336,9 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
children: [ children: [
// Main content // Main content
const Positioned( const Positioned(
child: PointsGainedAnimation(), child: PointsGainedAnimation(
origin: AnalyticsUpdateOrigin.practiceActivity,
),
), ),
if (activityWidget != null) if (activityWidget != null)
Padding( Padding(

@ -29,7 +29,9 @@ class TargetTokensController {
_targetTokens = await _initialize(context, pangeaMessageEvent); _targetTokens = await _initialize(context, pangeaMessageEvent);
await updateTokensWithConstructs( await updateTokensWithConstructs(
MatrixState.pangeaController.analytics.analyticsStream.value ?? [], MatrixState
.pangeaController.analytics.analyticsStream.value?.constructs ??
[],
context, context,
pangeaMessageEvent, pangeaMessageEvent,
); );
@ -58,9 +60,8 @@ class TargetTokensController {
return _targetTokens = []; return _targetTokens = [];
} }
return _targetTokens = tokens return _targetTokens =
.map((token) => token.emptyTokenWithXP) tokens.map((token) => token.emptyTokenWithXP).toList();
.toList();
} }
Future<void> updateTokensWithConstructs( Future<void> updateTokensWithConstructs(
@ -76,9 +77,8 @@ class TargetTokensController {
_targetTokens ??= await _initialize(context, pangeaMessageEvent); _targetTokens ??= await _initialize(context, pangeaMessageEvent);
for (final token in _targetTokens!) { for (final token in _targetTokens!) {
// we don't need to do this for tokens that don't have saveVocab set to true // 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; continue;
} }

@ -79,6 +79,7 @@ class WordFocusListeningActivityState
widget.practiceCardController.currentActivity!, widget.practiceCardController.currentActivity!,
widget.practiceCardController.metadata, widget.practiceCardController.metadata,
), ),
origin: AnalyticsUpdateOrigin.practiceActivity,
), ),
); );
setState(() { setState(() {

Loading…
Cancel
Save