feat: finish up level-up animation
Take out testing button and functions, lower XP needed in staging to level up for test reasons
This commit is contained in:
parent
e52d72cdb4
commit
0c244540e1
7 changed files with 69 additions and 148 deletions
|
|
@ -1,13 +1,12 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
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';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'settings_chat.dart';
|
||||
|
||||
class SettingsChatView extends StatelessWidget {
|
||||
|
|
@ -29,16 +28,6 @@ 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,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A wrapper around a list of [OneConstructUse]s, used to simplify
|
||||
/// the process of filtering / sorting / displaying the events.
|
||||
|
|
@ -35,7 +34,8 @@ class ConstructListModel {
|
|||
|
||||
/// [D] is the "compression factor". It determines how quickly
|
||||
/// or slowly the level grows relative to XP
|
||||
final double D = 1500;
|
||||
|
||||
final double D = Environment.isStagingEnvironment ? 500 : 1500;
|
||||
|
||||
List<ConstructIdentifier> unlockedLemmas(
|
||||
ConstructTypeEnum type, {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_list_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
|
|
@ -23,6 +17,10 @@ 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';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
/// A minimized version of AnalyticsController that get the logged in user's analytics
|
||||
class GetAnalyticsController extends BaseController {
|
||||
|
|
@ -484,7 +482,6 @@ class GetAnalyticsController extends BaseController {
|
|||
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;
|
||||
|
||||
// compute construct use of current level
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart';
|
||||
|
|
@ -13,6 +10,7 @@ import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_popup.dart';
|
|||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LevelUpConstants {
|
||||
static const String starFileName = "star.png";
|
||||
|
|
@ -103,7 +101,6 @@ class LevelUpBannerState extends State<LevelUpBanner>
|
|||
context,
|
||||
widget.level,
|
||||
widget.prevLevel,
|
||||
true, //value true if testing, false if real data
|
||||
);
|
||||
|
||||
_slideController = AnimationController(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.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 so analytics can be generated when level up is initiated, and be ready by the time user clicks on banner
|
||||
|
|
@ -34,14 +32,13 @@ class LevelUpManager {
|
|||
BuildContext context,
|
||||
int level,
|
||||
int prevLevel,
|
||||
bool test,
|
||||
) async {
|
||||
this.level = level;
|
||||
this.prevLevel = prevLevel;
|
||||
|
||||
//For on route change behavior, if added in the future
|
||||
shouldAutoPopup = true;
|
||||
|
||||
//grammar and vocab
|
||||
nextGrammar = MatrixState
|
||||
.pangeaController.getAnalytics.constructListModel.grammarLemmas;
|
||||
nextVocab = MatrixState
|
||||
|
|
@ -51,12 +48,7 @@ class LevelUpManager {
|
|||
.activeL2Code()
|
||||
?.toUpperCase();
|
||||
|
||||
// fetch construct summary based on test value
|
||||
if (test) {
|
||||
getConstructFromButton();
|
||||
} else {
|
||||
getConstructFromLevelUp();
|
||||
}
|
||||
getConstructFromLevelUp();
|
||||
|
||||
final LanguageModel? l2 =
|
||||
MatrixState.pangeaController.languageController.userL2;
|
||||
|
|
@ -75,10 +67,6 @@ class LevelUpManager {
|
|||
)
|
||||
.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)
|
||||
|
|
@ -89,21 +77,20 @@ class LevelUpManager {
|
|||
: 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;
|
||||
prevGrammar = (nextGrammar / prevLevel) as int;
|
||||
prevVocab = (nextVocab / prevLevel) as int;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//for testing, just fetch last level up from saved analytics
|
||||
void getConstructFromButton() {
|
||||
//for testing, just fetch last level up from saved analytics
|
||||
constructSummary = MatrixState.pangeaController.getAnalytics
|
||||
.getConstructSummaryFromStateEvent();
|
||||
debugPrint(
|
||||
|
|
@ -111,8 +98,8 @@ class LevelUpManager {
|
|||
);
|
||||
}
|
||||
|
||||
//for getting real level up data when leveled up
|
||||
void getConstructFromLevelUp() async {
|
||||
//for getting real level up data when leveled up
|
||||
try {
|
||||
constructSummary = await MatrixState.pangeaController.getAnalytics
|
||||
.generateLevelUpAnalytics(
|
||||
|
|
@ -124,19 +111,6 @@ class LevelUpManager {
|
|||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
shouldAutoPopup = false;
|
||||
|
|
@ -153,6 +127,5 @@ class LevelUpManager {
|
|||
nextVocab = 0;
|
||||
constructSummary = null;
|
||||
error = null;
|
||||
// Reset any other state if necessary
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:animated_flip_counter/animated_flip_counter.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:confetti/confetti.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:matrix/matrix_api_lite/generated/model.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart';
|
||||
|
|
@ -23,6 +17,10 @@ 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';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:matrix/matrix_api_lite/generated/model.dart';
|
||||
|
||||
class LevelUpPopup extends StatelessWidget {
|
||||
const LevelUpPopup({
|
||||
|
|
@ -74,24 +72,21 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
with SingleTickerProviderStateMixin {
|
||||
late int _endGrammar;
|
||||
late int _endVocab;
|
||||
late final AnimationController _controller;
|
||||
|
||||
Uri? avatarUrl;
|
||||
late final Future<Profile> profile;
|
||||
|
||||
late final ConfettiController _confettiController;
|
||||
|
||||
int displayedLevel = -1;
|
||||
bool _hasBlastedConfetti = false;
|
||||
|
||||
final int _startGrammar = LevelUpManager.instance.prevGrammar;
|
||||
final int _startVocab = LevelUpManager.instance.prevVocab;
|
||||
late ConstructSummary? _constructSummary;
|
||||
Timer? _summaryPollTimer;
|
||||
final String? _error = LevelUpManager.instance.error;
|
||||
String language = LevelUpManager.instance.userL2Code ?? "N/A";
|
||||
|
||||
static const Duration _animationDuration = Duration(seconds: 5);
|
||||
late final AnimationController _controller;
|
||||
late final ConfettiController _confettiController;
|
||||
bool _hasBlastedConfetti = false;
|
||||
final Duration _animationDuration = const Duration(seconds: 5);
|
||||
|
||||
Uri? avatarUrl;
|
||||
late final Future<Profile> profile;
|
||||
int displayedLevel = -1;
|
||||
late ConstructSummary? _constructSummary;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -269,7 +264,7 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
builder: (context, constraints) {
|
||||
return LevelBar(
|
||||
details: const LevelBarDetails(
|
||||
fillColor: Colors.green,
|
||||
fillColor: AppConfig.goldLight,
|
||||
currentPoints: 0,
|
||||
widthMultiplier: 1,
|
||||
),
|
||||
|
|
@ -392,7 +387,6 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: CachedNetworkImage(
|
||||
|
|
@ -419,41 +413,41 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
),
|
||||
),
|
||||
// Share button, currently no functionality
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// Add share functionality
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.black,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 24,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Share with Friends",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Icon(
|
||||
Icons.ios_share,
|
||||
size: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// // Add share functionality
|
||||
// },
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Colors.white,
|
||||
// foregroundColor: Colors.black,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// vertical: 12,
|
||||
// horizontal: 24,
|
||||
// ),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Row(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Share with Friends",
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.ios_share,
|
||||
// size: 20,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -467,7 +461,7 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
.toList();
|
||||
|
||||
const itemsPerRow = 4;
|
||||
// chunk into rows of up to 3
|
||||
// chunk into rows of up to 4
|
||||
final rows = <List<LearningSkillsEnum>>[
|
||||
for (var i = 0; i < visibleSkills.length; i += itemsPerRow)
|
||||
visibleSkills.sublist(
|
||||
|
|
@ -522,32 +516,4 @@ class _LevelUpPopupContentState extends State<LevelUpPopupContent>
|
|||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Path drawStar(Size size) {
|
||||
// Method to convert degrees to radians
|
||||
double degToRad(double deg) => deg * (pi / 180.0);
|
||||
|
||||
const numberOfPoints = 5;
|
||||
final halfWidth = size.width / 2;
|
||||
final externalRadius = halfWidth;
|
||||
final internalRadius = halfWidth / 2.5;
|
||||
final degreesPerStep = degToRad(360 / numberOfPoints);
|
||||
final halfDegreesPerStep = degreesPerStep / 2;
|
||||
final path = Path();
|
||||
final fullAngle = degToRad(360);
|
||||
path.moveTo(size.width, halfWidth);
|
||||
|
||||
for (double step = 0; step < fullAngle; step += degreesPerStep) {
|
||||
path.lineTo(
|
||||
halfWidth + externalRadius * cos(step),
|
||||
halfWidth + externalRadius * sin(step),
|
||||
);
|
||||
path.lineTo(
|
||||
halfWidth + internalRadius * cos(step + halfDegreesPerStep),
|
||||
halfWidth + internalRadius * sin(step + halfDegreesPerStep),
|
||||
);
|
||||
}
|
||||
path.close();
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ void rainConfetti(BuildContext context) {
|
|||
_rainController!.play();
|
||||
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
final isSmallScreen = screenWidth < 600;
|
||||
final count = isSmallScreen ? 2 : 5;
|
||||
final spacing = screenWidth / (count + 1);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue