From 570d5e511dd51a7bfac1e6b55c4c5cf9cbdfb29e Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Wed, 1 Oct 2025 10:00:53 -0400 Subject: [PATCH] chore: wait for user to send at least 3 text or audio messages before showing overlay with instructions about clicking activity status button --- .../activity_stats_button.dart | 88 ++++++++++++------- .../activity_stats_menu.dart | 12 --- .../event_wrappers/pangea_message_event.dart | 1 - 3 files changed, 57 insertions(+), 44 deletions(-) diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_stats_button.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_stats_button.dart index 2d79a9e5c..e14443f1e 100644 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_stats_button.dart +++ b/lib/pangea/activity_sessions/activity_session_chat/activity_stats_button.dart @@ -44,11 +44,58 @@ class _ActivityStatsButtonState extends State { .listen((_) => _updateAnalytics()); } - Client get client => widget.controller.room.client; + @override + void dispose() { + _analyticsSubscription?.cancel(); + super.dispose(); + } - void _showInstructionPopup() { + Client get _client => widget.controller.room.client; + + bool get _shouldShowInstructions { if (InstructionsEnum.activityStatsMenu.isToggledOff || - (xpCount ?? 0) <= 0) { + _xpCount <= 0 || + widget.controller.timeline == null) { + return false; + } + + int count = 0; + for (final event in widget.controller.timeline!.events) { + if (event.senderId == _client.userID && + event.type == EventTypes.Message && + [ + MessageTypes.Text, + MessageTypes.Audio, + ].contains(event.messageType)) { + count++; + } + + if (count >= 3) return true; + } + + return false; + } + + int get _xpCount => + analytics?.totalXPForUser( + _client.userID!, + ) ?? + 0; + + int? get _vocabCount => analytics?.uniqueConstructCountForUser( + _client.userID!, + ConstructTypeEnum.vocab, + ); + + int? get _grammarCount => analytics?.uniqueConstructCountForUser( + _client.userID!, + ConstructTypeEnum.morph, + ); + + /// Show a tutorial overlay that blocks the screen and points + /// to the stats menu button with an explanation of what it does. + void _showStatsMenuDropdownInstructions() { + if (!_shouldShowInstructions) { return; } @@ -107,32 +154,11 @@ class _ActivityStatsButtonState extends State { ); } - @override - void dispose() { - _analyticsSubscription?.cancel(); - super.dispose(); - } - - int? get xpCount => analytics?.totalXPForUser( - client.userID!, - ); - - int? get vocabCount => analytics?.uniqueConstructCountForUser( - client.userID!, - ConstructTypeEnum.vocab, - ); - - int? get grammarCount => analytics?.uniqueConstructCountForUser( - client.userID!, - ConstructTypeEnum.morph, - ); - Future _updateAnalytics() async { - final prevXP = xpCount; final analytics = await widget.controller.room.getActivityAnalytics(); if (mounted) { setState(() => this.analytics = analytics); - if (prevXP == 0 && (xpCount ?? 0) > 0) _showInstructionPopup(); + _showStatsMenuDropdownInstructions(); } } @@ -144,17 +170,17 @@ class _ActivityStatsButtonState extends State { !widget.controller.showActivityDropdown, ), borderRadius: BorderRadius.circular(12), - color: (xpCount ?? 0) > 0 + color: _xpCount > 0 ? AppConfig.gold.withAlpha(180) : theme.colorScheme.surface, - depressed: (xpCount ?? 0) <= 0 || widget.controller.showActivityDropdown, + depressed: _xpCount <= 0 || widget.controller.showActivityDropdown, child: AnimatedContainer( duration: FluffyThemes.animationDuration, width: 300, height: 55, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( - color: (xpCount ?? 0) > 0 + color: _xpCount > 0 ? AppConfig.gold.withAlpha(180) : theme.colorScheme.surface, borderRadius: BorderRadius.circular(12), @@ -164,11 +190,11 @@ class _ActivityStatsButtonState extends State { : Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - _StatsBadge(icon: Icons.radar, value: "$xpCount XP"), - _StatsBadge(icon: Symbols.dictionary, value: "$vocabCount"), + _StatsBadge(icon: Icons.radar, value: "$_xpCount XP"), + _StatsBadge(icon: Symbols.dictionary, value: "$_vocabCount"), _StatsBadge( icon: Symbols.toys_and_games, - value: "$grammarCount", + value: "$_grammarCount", ), ], ), diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_stats_menu.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_stats_menu.dart index d089dc8bf..e4f782903 100644 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_stats_menu.dart +++ b/lib/pangea/activity_sessions/activity_session_chat/activity_stats_menu.dart @@ -82,18 +82,6 @@ class ActivityStatsMenuState extends State { return nonBotRoles.length; } - int _getCompletedRolesCount() { - final assignedRoles = room.assignedRoles; - if (assignedRoles == null) return 0; - - // Filter out the bot and count only finished non-bot roles - return assignedRoles.values - .where( - (role) => role.userId != BotName.byEnvironment && role.isFinished, - ) - .length; - } - bool _isBotParticipant() { final assignedRoles = room.assignedRoles; if (assignedRoles == null) return false; diff --git a/lib/pangea/events/event_wrappers/pangea_message_event.dart b/lib/pangea/events/event_wrappers/pangea_message_event.dart index aafdad1f3..fd410a3ba 100644 --- a/lib/pangea/events/event_wrappers/pangea_message_event.dart +++ b/lib/pangea/events/event_wrappers/pangea_message_event.dart @@ -73,7 +73,6 @@ class PangeaMessageEvent { String? get mimetype { if (!isAudioMessage) return null; final Map? info = _event.content.tryGetMap("info"); - debugPrint("INFO: $info"); if (info == null) return null; return info["mime_type"] ?? info["mimetype"]; }