diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 3b8acf876..96cc4d7e9 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -5310,5 +5310,6 @@ "activityAnalyticsTooltipBody": "These are your saved activities for review and practice.", "numSavedActivities": "Number of saved activities", "saveActivityTitle": "Save activity", - "saveActivityDesc": "Good job! Save this activity for later review and practice" + "saveActivityDesc": "Good job! Save this activity for later review and practice", + "levelInfoTooltip": "Here you can see all the points you’ve earned and how!" } diff --git a/lib/pangea/analytics_details_popup/analytics_details_popup_content.dart b/lib/pangea/analytics_details_popup/analytics_details_popup_content.dart index ca8eefbe3..4cf7bca0e 100644 --- a/lib/pangea/analytics_details_popup/analytics_details_popup_content.dart +++ b/lib/pangea/analytics_details_popup/analytics_details_popup_content.dart @@ -1,11 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:cached_network_image/cached_network_image.dart'; - -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/analytics_details_popup/lemma_usage_dots.dart'; import 'package:fluffychat/pangea/analytics_details_popup/lemma_use_example_messages.dart'; -import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; @@ -43,14 +39,9 @@ class AnalyticsDetailsViewContent extends StatelessWidget { subtitle, const SizedBox(height: 16.0), headerContent, - Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: CachedNetworkImage( - imageUrl: - "${AppConfig.assetsBaseURL}/${AnalyticsConstants.popupDividerFileName}", - placeholder: (context, url) => const CircularProgressIndicator(), - errorWidget: (context, url, error) => const Icon(Icons.error), - ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Divider(), ), Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart b/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart index 4966af84d..c5f26da2e 100644 --- a/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart +++ b/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart @@ -164,7 +164,7 @@ class MorphFeatureBox extends StatelessWidget { morphTag: morphTag, constructAnalytics: analytics, onTap: () => context.go( - "/rooms/analytics/${id.type.string}/${id.string}", + "/rooms/analytics/${id.type.string}/${Uri.encodeComponent(id.string)}", ), ); }, diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart index 78ae5dbe0..120bf427a 100644 --- a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart +++ b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart @@ -175,7 +175,7 @@ class VocabAnalyticsListView extends StatelessWidget { final vocabItem = _filteredVocab[index]; return VocabAnalyticsListTile( onTap: () => context.go( - "/rooms/analytics/${vocabItem.id.type.string}/${vocabItem.id.string}", + "/rooms/analytics/${vocabItem.id.type.string}/${Uri.encodeComponent(vocabItem.id.string)}", ), constructUse: vocabItem, emoji: vocabItem.id.userSetEmoji.firstOrNull, diff --git a/lib/pangea/analytics_misc/analytics_constants.dart b/lib/pangea/analytics_misc/analytics_constants.dart index cff83fcc1..d680c1fd7 100644 --- a/lib/pangea/analytics_misc/analytics_constants.dart +++ b/lib/pangea/analytics_misc/analytics_constants.dart @@ -12,7 +12,6 @@ class AnalyticsConstants { static const String emojiForFlower = "🌸"; static const levelUpAudioFileName = "LevelUp_chime.mp3"; static const levelUpImageFileName = "LvL_Up_Full_Banner.png"; - static const popupDividerFileName = "divider.png"; static const vocabIconFileName = "Vocabulary_icon.png"; static const morphIconFileName = "grammar_icon.png"; } diff --git a/lib/pangea/analytics_misc/get_analytics_controller.dart b/lib/pangea/analytics_misc/get_analytics_controller.dart index f8963c88b..3b1c7b085 100644 --- a/lib/pangea/analytics_misc/get_analytics_controller.dart +++ b/lib/pangea/analytics_misc/get_analytics_controller.dart @@ -110,7 +110,7 @@ class GetAnalyticsController extends BaseController { ); } finally { _updateAnalyticsStream( - type: AnalyticsUpdateType.local, + type: AnalyticsUpdateType.init, points: 0, newConstructs: [], ); diff --git a/lib/pangea/analytics_misc/put_analytics_controller.dart b/lib/pangea/analytics_misc/put_analytics_controller.dart index 0df72b647..eb1d9006c 100644 --- a/lib/pangea/analytics_misc/put_analytics_controller.dart +++ b/lib/pangea/analytics_misc/put_analytics_controller.dart @@ -15,7 +15,7 @@ import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/widgets/matrix.dart'; -enum AnalyticsUpdateType { server, local, activities } +enum AnalyticsUpdateType { server, local, activities, init } /// handles the processing of analytics for /// 1) messages sent by the user and diff --git a/lib/pangea/analytics_page/analytics_page.dart b/lib/pangea/analytics_page/analytics_page.dart index d1efb4bd0..0c485224a 100644 --- a/lib/pangea/analytics_page/analytics_page.dart +++ b/lib/pangea/analytics_page/analytics_page.dart @@ -7,6 +7,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart'; import 'package:fluffychat/pangea/analytics_page/activity_archive.dart'; import 'package:fluffychat/pangea/analytics_page/analytics_page_constants.dart'; import 'package:fluffychat/pangea/analytics_summary/learning_progress_indicators.dart'; @@ -15,7 +16,7 @@ import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dar import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/widgets/matrix.dart'; -class AnalyticsPage extends StatefulWidget { +class AnalyticsPage extends StatelessWidget { final ProgressIndicatorEnum? indicator; final ConstructIdentifier? construct; final bool isSidebar; @@ -27,84 +28,73 @@ class AnalyticsPage extends StatefulWidget { this.isSidebar = false, }); - @override - State createState() => _AnalyticsPageState(); -} - -class _AnalyticsPageState extends State { - @override - void initState() { - super.initState(); - final analytics = MatrixState.pangeaController.getAnalytics; - - // Check if getAnalytics is initialized, if not wait for the first stream entry - if (!analytics.initCompleter.isCompleted) { - analytics.analyticsStream.stream.first.then((_) { - if (mounted) { - setState(() {}); - } - }); - } - } - @override Widget build(BuildContext context) { final analyticsRoomId = GoRouterState.of(context).pathParameters['roomid']; return Scaffold( - appBar: widget.construct != null ? AppBar() : null, + appBar: construct != null ? AppBar() : null, body: SafeArea( - child: Padding( - padding: const EdgeInsetsGeometry.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.isSidebar || - (!FluffyThemes.isColumnMode(context) && - widget.construct == null)) - LearningProgressIndicators( - selected: widget.indicator, - canSelect: widget.indicator != ProgressIndicatorEnum.level, - ), - Expanded( - child: () { - if (widget.indicator == ProgressIndicatorEnum.level) { - return const LevelDialogContent(); - } else if (widget.indicator == - ProgressIndicatorEnum.morphsUsed) { - return ConstructAnalyticsView( - construct: widget.construct, - view: ConstructTypeEnum.morph, - ); - } else if (widget.indicator == - ProgressIndicatorEnum.wordsUsed) { - return ConstructAnalyticsView( - construct: widget.construct, - view: ConstructTypeEnum.vocab, - ); - } else if (widget.indicator == - ProgressIndicatorEnum.activities) { - return ActivityArchive( - selectedRoomId: analyticsRoomId, - ); - } - - return Center( - child: SizedBox( - width: 250.0, - child: CachedNetworkImage( - imageUrl: - "${AppConfig.assetsBaseURL}/${AnalyticsPageConstants.dinoBotFileName}", - errorWidget: (context, url, error) => const SizedBox(), - placeholder: (context, url) => const Center( - child: CircularProgressIndicator.adaptive(), - ), - ), - ), - ); - }(), - ), - ], + child: StreamBuilder( + stream: MatrixState + .pangeaController.getAnalytics.analyticsStream.stream + .where( + (u) => u.type == AnalyticsUpdateType.init, ), + builder: (context, snapshot) { + return Padding( + padding: const EdgeInsetsGeometry.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (isSidebar || + (!FluffyThemes.isColumnMode(context) && + construct == null)) + LearningProgressIndicators( + selected: indicator, + canSelect: indicator != ProgressIndicatorEnum.level, + ), + Expanded( + child: () { + if (indicator == ProgressIndicatorEnum.level) { + return const LevelDialogContent(); + } else if (indicator == + ProgressIndicatorEnum.morphsUsed) { + return ConstructAnalyticsView( + construct: construct, + view: ConstructTypeEnum.morph, + ); + } else if (indicator == ProgressIndicatorEnum.wordsUsed) { + return ConstructAnalyticsView( + construct: construct, + view: ConstructTypeEnum.vocab, + ); + } else if (indicator == + ProgressIndicatorEnum.activities) { + return ActivityArchive( + selectedRoomId: analyticsRoomId, + ); + } + + return Center( + child: SizedBox( + width: 250.0, + child: CachedNetworkImage( + imageUrl: + "${AppConfig.assetsBaseURL}/${AnalyticsPageConstants.dinoBotFileName}", + errorWidget: (context, url, error) => + const SizedBox(), + placeholder: (context, url) => const Center( + child: CircularProgressIndicator.adaptive(), + ), + ), + ), + ); + }(), + ), + ], + ), + ); + }, ), ), ); diff --git a/lib/pangea/analytics_summary/level_dialog_content.dart b/lib/pangea/analytics_summary/level_dialog_content.dart index 8ee525a2b..f87255a31 100644 --- a/lib/pangea/analytics_summary/level_dialog_content.dart +++ b/lib/pangea/analytics_summary/level_dialog_content.dart @@ -7,6 +7,8 @@ import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart'; +import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; +import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -72,8 +74,16 @@ class LevelDialogContent extends StatelessWidget { children: [ Expanded( child: ListView.builder( - itemCount: uses.length, + itemCount: uses.length + 1, itemBuilder: (context, index) { + if (index == 0) { + return const InstructionsInlineTooltip( + instructionsEnum: InstructionsEnum.levelAnalytics, + padding: EdgeInsets.symmetric(vertical: 16.0), + ); + } + index--; + final use = uses[index]; String lemmaCopy = use.lemma; if (use.constructType == ConstructTypeEnum.morph) { diff --git a/lib/pangea/chat/utils/unlocked_morphs_snackbar.dart b/lib/pangea/chat/utils/unlocked_morphs_snackbar.dart index 06ad1fdb9..193b84799 100644 --- a/lib/pangea/chat/utils/unlocked_morphs_snackbar.dart +++ b/lib/pangea/chat/utils/unlocked_morphs_snackbar.dart @@ -168,7 +168,7 @@ class ConstructNotificationOverlayState void _showDetails() { context.go( - "/rooms/analytics/${ConstructTypeEnum.morph.string}/${widget.construct.string}", + "/rooms/analytics/${ConstructTypeEnum.morph.string}/${Uri.encodeComponent(widget.construct.string)}", ); } diff --git a/lib/pangea/instructions/instructions_enum.dart b/lib/pangea/instructions/instructions_enum.dart index 077f41025..b1cb51701 100644 --- a/lib/pangea/instructions/instructions_enum.dart +++ b/lib/pangea/instructions/instructions_enum.dart @@ -22,6 +22,7 @@ enum InstructionsEnum { analyticsVocabList, morphAnalyticsList, activityAnalyticsList, + levelAnalytics, readingAssistanceOverview, emptyChatWarning, activityStatsMenu, @@ -51,6 +52,7 @@ extension InstructionsEnumExtension on InstructionsEnum { case InstructionsEnum.activityStatsMenu: case InstructionsEnum.chatListTooltip: case InstructionsEnum.activityAnalyticsList: + case InstructionsEnum.levelAnalytics: ErrorHandler.logError( e: Exception("No title for this instruction"), m: 'InstructionsEnumExtension.title', @@ -105,6 +107,8 @@ extension InstructionsEnumExtension on InstructionsEnum { return l10n.activityStatsButtonInstruction; case InstructionsEnum.chatListTooltip: return l10n.chatListTooltip; + case InstructionsEnum.levelAnalytics: + return l10n.levelInfoTooltip; } }