diff --git a/lib/pages/settings_chat/settings_chat_view.dart b/lib/pages/settings_chat/settings_chat_view.dart index 58eec8d46..e3e5efe5f 100644 --- a/lib/pages/settings_chat/settings_chat_view.dart +++ b/lib/pages/settings_chat/settings_chat_view.dart @@ -2,6 +2,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; +import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_banner.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/settings_switch_list_tile.dart'; @@ -28,6 +29,16 @@ class SettingsChatView extends StatelessWidget { child: MaxWidthBody( child: Column( children: [ + ElevatedButton( + onPressed: () { + LevelUpUtil.showLevelUpDialog( + 3, + 2, + context, + ); + }, + child: const Text('Show Level Up Dialog'), + ), // #Pangea // SettingsSwitchListTile.adaptive( // title: L10n.of(context).formattedMessages, diff --git a/lib/pangea/analytics_misc/get_analytics_controller.dart b/lib/pangea/analytics_misc/get_analytics_controller.dart index 3413cc9f5..b328097c3 100644 --- a/lib/pangea/analytics_misc/get_analytics_controller.dart +++ b/lib/pangea/analytics_misc/get_analytics_controller.dart @@ -16,6 +16,7 @@ import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:get_storage/get_storage.dart'; import 'package:matrix/matrix.dart'; @@ -478,8 +479,8 @@ class GetAnalyticsController extends BaseController { // generate level up analytics as a construct summary ConstructSummary summary; try { - final int maxXP = constructListModel.calculateXpWithLevel(lowerLevel); - final int minXP = constructListModel.calculateXpWithLevel(upperLevel); + final int maxXP = constructListModel.calculateXpWithLevel(upperLevel); + final int minXP = constructListModel.calculateXpWithLevel(lowerLevel); int diffXP = maxXP - minXP; debugPrint("minXP: $minXP, maxXP: $maxXP, diffXP: $diffXP"); if (diffXP < 0) diffXP = 0; @@ -523,6 +524,10 @@ class GetAnalyticsController extends BaseController { final response = await ConstructRepo.generateConstructSummary(request); summary = response.summary; + summary.levelVocabConstructs = MatrixState + .pangeaController.getAnalytics.constructListModel.vocabLemmas; + summary.levelGrammarConstructs = MatrixState + .pangeaController.getAnalytics.constructListModel.grammarLemmas; } catch (e) { debugPrint("Error generating level up analytics: $e"); ErrorHandler.logError(e: e, data: {'e': e}); diff --git a/lib/pangea/analytics_misc/level_up/level_up_banner.dart b/lib/pangea/analytics_misc/level_up/level_up_banner.dart index ad0b840e4..8dff08370 100644 --- a/lib/pangea/analytics_misc/level_up/level_up_banner.dart +++ b/lib/pangea/analytics_misc/level_up/level_up_banner.dart @@ -101,6 +101,7 @@ class LevelUpBannerState extends State context, widget.level, widget.prevLevel, + true, //value true if testing, false if real data ); _slideController = AnimationController( diff --git a/lib/pangea/analytics_misc/level_up/level_up_manager.dart b/lib/pangea/analytics_misc/level_up/level_up_manager.dart index 806ad7477..e458730a1 100644 --- a/lib/pangea/analytics_misc/level_up/level_up_manager.dart +++ b/lib/pangea/analytics_misc/level_up/level_up_manager.dart @@ -1,13 +1,15 @@ -import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart'; import 'package:fluffychat/pangea/constructs/construct_repo.dart'; +import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; class LevelUpManager { - // Singleton instance + // Singleton instance so analytics can be generated when level up is initiated, and be ready by the time user clicks on banner static final LevelUpManager instance = LevelUpManager._internal(); - // Private constructor LevelUpManager._internal(); int prevLevel = 0; @@ -26,15 +28,11 @@ class LevelUpManager { bool shouldAutoPopup = false; String? error; - int get vocabCount => - MatrixState.pangeaController.getAnalytics.constructListModel - .unlockedLemmas(ConstructTypeEnum.vocab) - .length; - Future preloadAnalytics( BuildContext context, int level, int prevLevel, + bool test, ) async { this.level = level; this.prevLevel = prevLevel; @@ -47,75 +45,95 @@ class LevelUpManager { nextVocab = MatrixState .pangeaController.getAnalytics.constructListModel.vocabLemmas; - //for now idk how to get these - prevGrammar = nextGrammar < 30 ? 0 : nextGrammar - 30; - - prevVocab = nextVocab < 30 ? 0 : nextVocab - 30; - userL2Code = MatrixState.pangeaController.languageController .activeL2Code() ?.toUpperCase(); - /*for testing, just fetch last level up + // fetch construct summary based on test value + if (test) { + getConstructFromButton(); + } else { + getConstructFromLevelUp(); + } + + final LanguageModel? l2 = + MatrixState.pangeaController.languageController.userL2; + final Room? analyticsRoom = + MatrixState.pangeaController.matrixState.client.analyticsRoomLocal(l2!); + + if (analyticsRoom != null) { + // How to get all summary events in the timeline + final timeline = await analyticsRoom.getTimeline(); + final summaryEvents = timeline.events + .where( + (e) => e.type == PangeaEventTypes.constructSummary, + ) + .map( + (e) => ConstructSummary.fromJson(e.content), + ) + .toList(); + + debugPrint("List of all previous level up summaries: $summaryEvents"); + for (final summary in summaryEvents) { + debugPrint("${summary.toJson()}"); + } + //Find previous summary to get grammar constructs and vocab numbers from + final lastSummary = summaryEvents + .where((summary) => summary.upperLevel == prevLevel) + .toList() + .isNotEmpty + ? summaryEvents + .firstWhere((summary) => summary.upperLevel == prevLevel) + : null; + + //Set grammar and vocab from last level summary, if there is one. Otherwise set to placeholder data + debugPrint("Last construct summary is: ${lastSummary?.toJson()}"); + if (lastSummary != null && + lastSummary.levelVocabConstructs != null && + lastSummary.levelGrammarConstructs != null) { + prevVocab = lastSummary.levelVocabConstructs!; + prevGrammar = lastSummary.levelGrammarConstructs!; + } else { + prevGrammar = nextGrammar < 30 ? 0 : nextGrammar - 30; + prevVocab = nextVocab < 30 ? 0 : nextVocab - 30; + } + } + } + + void getConstructFromButton() { + //for testing, just fetch last level up from saved analytics constructSummary = MatrixState.pangeaController.getAnalytics .getConstructSummaryFromStateEvent(); debugPrint( - "Last saved construct summary: ${constructSummary?.toJson()}", + "Last saved construct summary from analytics controller function: ${constructSummary?.toJson()}", ); + } - final client = MatrixState.pangeaController.matrixState.client; - - final Room? analyticsRoom = client.analyticsRoomLocal( - MatrixState.pangeaController.languageController.userL2!, - ); - - // Get all summary events in the timeline - final timeline = await analyticsRoom!.getTimeline(); - final summaryEvents = timeline.events - .where( - (e) => e.type == PangeaEventTypes.constructSummary, - ) - .map( - (e) => ConstructSummary.fromJson(e.content), - ) - .toList(); - debugPrint("List of previous summaries from timeline: $summaryEvents"); - - for (final summary in summaryEvents) { - debugPrint("Individual summaries from timeline: ${summary.toJson()}"); - } - - */ - - // fetch construct summary for actual app, not while testing since level up isn't true + void getConstructFromLevelUp() async { + //for getting real level up data when leveled up try { constructSummary = await MatrixState.pangeaController.getAnalytics .generateLevelUpAnalytics( - level, prevLevel, + level, ); } catch (e) { error = e.toString(); } - // end of that block - await Future.delayed( - const Duration(seconds: 1), - () => LevelUpManager.instance.printAnalytics(), - ); } - void printAnalytics() { - debugPrint('Level Up Analytics:'); - debugPrint('Current Level: $level'); - debugPrint('Previous Level: $prevLevel'); - debugPrint('Next Grammar: $nextGrammar'); - debugPrint('Next Vocab: $nextVocab'); - if (constructSummary != null) { - debugPrint('Construct Summary: ${constructSummary!.toJson()}'); - } else { - debugPrint('Construct Summary: Not available'); - } - } + // void printAnalytics() { + // debugPrint('Level Up Analytics:'); + // debugPrint('Current Level: $level'); + // debugPrint('Previous Level: $prevLevel'); + // debugPrint('Next Grammar: $nextGrammar'); + // debugPrint('Next Vocab: $nextVocab'); + // if (constructSummary != null) { + // debugPrint('Construct Summary: ${constructSummary!.toJson()}'); + // } else { + // debugPrint('Construct Summary: Not available'); + // } + // } void markPopupSeen() { hasSeenPopup = true; diff --git a/lib/pangea/analytics_misc/level_up/level_up_popup.dart b/lib/pangea/analytics_misc/level_up/level_up_popup.dart index 4055cbe85..1a50ba197 100644 --- a/lib/pangea/analytics_misc/level_up/level_up_popup.dart +++ b/lib/pangea/analytics_misc/level_up/level_up_popup.dart @@ -14,6 +14,7 @@ import 'package:fluffychat/pangea/analytics_summary/progress_bar/level_bar.dart' import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; import 'package:fluffychat/pangea/constructs/construct_repo.dart'; +import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/mxc_image.dart'; import 'package:flutter/foundation.dart'; @@ -214,6 +215,8 @@ class _LevelUpPopupContentState extends State fontWeight: FontWeight.bold, color: colorScheme.primary, ); + final username = + Matrix.of(context).client.userID?.split(':').first.substring(1) ?? ''; return Stack( children: [ @@ -230,11 +233,10 @@ class _LevelUpPopupContentState extends State Padding( padding: const EdgeInsets.all(24.0), child: avatarUrl == null - ? MxcImage( - client: Matrix.of(context).client, - fit: BoxFit.cover, - width: 150 * shrinkMultiplier.value, - height: 150 * shrinkMultiplier.value, + ? Avatar( + name: username, + showPresence: false, + size: 150 * shrinkMultiplier.value, ) : ClipOval( child: MxcImage( @@ -310,23 +312,58 @@ class _LevelUpPopupContentState extends State builder: (_, __) => Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Symbols.dictionary, - color: colorScheme.primary, - size: 35, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + "+ ${_endVocab - _startVocab}", + style: const TextStyle( + color: Colors.lightGreen, + fontWeight: FontWeight.bold, + ), + ), + Row( + children: [ + Icon( + Symbols.dictionary, + color: colorScheme.primary, + size: 35, + ), + const SizedBox(width: 8), + Text( + '${vocabAnimation.value}', + style: grammarVocabStyle, + ), + ], + ), + ], ), - const SizedBox(width: 8), - Text('${vocabAnimation.value}', style: grammarVocabStyle), const SizedBox(width: 40), - Icon( - Symbols.toys_and_games, - color: colorScheme.primary, - size: 35, - ), - const SizedBox(width: 8), - Text( - '${grammarAnimation.value}', - style: grammarVocabStyle, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + "+ ${_endGrammar - _startGrammar}", + style: const TextStyle( + color: Colors.lightGreen, + fontWeight: FontWeight.bold, + ), + ), + Row( + children: [ + Icon( + Symbols.toys_and_games, + color: colorScheme.primary, + size: 35, + ), + const SizedBox(width: 8), + Text( + '${grammarAnimation.value}', + style: grammarVocabStyle, + ), + ], + ), + ], ), ], ), diff --git a/lib/pangea/constructs/construct_repo.dart b/lib/pangea/constructs/construct_repo.dart index 6d97ce0af..f6fc19900 100644 --- a/lib/pangea/constructs/construct_repo.dart +++ b/lib/pangea/constructs/construct_repo.dart @@ -1,16 +1,17 @@ import 'dart:convert'; -import 'package:http/http.dart'; - import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/common/network/requests.dart'; import 'package:fluffychat/pangea/common/network/urls.dart'; import 'package:fluffychat/widgets/matrix.dart'; +import 'package:http/http.dart'; class ConstructSummary { final int upperLevel; final int lowerLevel; + int? levelVocabConstructs; + int? levelGrammarConstructs; final String language; final String textSummary; final int writingConstructScore; @@ -21,6 +22,8 @@ class ConstructSummary { ConstructSummary({ required this.upperLevel, required this.lowerLevel, + this.levelVocabConstructs, + this.levelGrammarConstructs, required this.language, required this.textSummary, required this.writingConstructScore, @@ -33,6 +36,8 @@ class ConstructSummary { return { 'upper_level': upperLevel, 'lower_level': lowerLevel, + 'level_grammar_constructs': levelGrammarConstructs, + 'level_vocab_constructs': levelVocabConstructs, 'language': language, 'text_summary': textSummary, 'writing_construct_score': writingConstructScore, @@ -46,6 +51,8 @@ class ConstructSummary { return ConstructSummary( upperLevel: json['upper_level'], lowerLevel: json['lower_level'], + levelGrammarConstructs: json['level_grammar_constructs'], + levelVocabConstructs: json['level_vocab_constructs'], language: json['language'], textSummary: json['text_summary'], writingConstructScore: json['writing_construct_score'],