From 43014b3207ec56f02b8225c340b7d65b78c0bddd Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 10 Dec 2025 16:05:14 -0500 Subject: [PATCH] chore: simplify progress bar widget --- .../level_up/level_popup_progess_bar.dart | 43 +++++++ .../level_up/level_up_popup.dart | 29 +---- .../learning_progress_bar.dart | 21 ++-- .../progress_bar/animated_level_dart.dart | 105 ------------------ .../progress_bar/animated_progress_bar.dart | 62 +++++++++++ .../progress_bar/level_bar.dart | 43 ------- .../progress_bar/progress_bar.dart | 64 ----------- .../progress_bar/progress_bar_background.dart | 30 ----- .../progress_bar/progress_bar_details.dart | 25 ----- 9 files changed, 118 insertions(+), 304 deletions(-) create mode 100644 lib/pangea/analytics_misc/level_up/level_popup_progess_bar.dart delete mode 100644 lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart create mode 100644 lib/pangea/analytics_summary/progress_bar/animated_progress_bar.dart delete mode 100644 lib/pangea/analytics_summary/progress_bar/level_bar.dart delete mode 100644 lib/pangea/analytics_summary/progress_bar/progress_bar.dart delete mode 100644 lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart delete mode 100644 lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart diff --git a/lib/pangea/analytics_misc/level_up/level_popup_progess_bar.dart b/lib/pangea/analytics_misc/level_up/level_popup_progess_bar.dart new file mode 100644 index 000000000..a7dbb34ce --- /dev/null +++ b/lib/pangea/analytics_misc/level_up/level_popup_progess_bar.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/animated_progress_bar.dart'; + +class LevelPopupProgressBar extends StatefulWidget { + final double height; + final Duration duration; + + const LevelPopupProgressBar({ + required this.height, + required this.duration, + super.key, + }); + + @override + LevelPopupProgressBarState createState() => LevelPopupProgressBarState(); +} + +class LevelPopupProgressBarState extends State { + double width = 0.0; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + width = 1.0; + }); + }); + } + + @override + Widget build(BuildContext context) { + return AnimatedProgressBar( + height: widget.height, + widthPercent: width, + barColor: AppConfig.goldLight, + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + duration: widget.duration, + ); + } +} 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 53a68d397..8795ab461 100644 --- a/lib/pangea/analytics_misc/level_up/level_up_popup.dart +++ b/lib/pangea/analytics_misc/level_up/level_up_popup.dart @@ -12,11 +12,10 @@ 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'; +import 'package:fluffychat/pangea/analytics_misc/level_up/level_popup_progess_bar.dart'; import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_banner.dart'; import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_manager.dart'; import 'package:fluffychat/pangea/analytics_misc/level_up/star_rain_widget.dart'; -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/error_indicator.dart'; import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; import 'package:fluffychat/pangea/constructs/construct_repo.dart'; @@ -193,11 +192,6 @@ class _LevelUpPopupContentState extends State @override @override Widget build(BuildContext context) { - final Animation progressAnimation = - Tween(begin: 0, end: 1).animate( - CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.5)), - ); - final Animation vocabAnimation = IntTween(begin: _startVocab, end: _endVocab).animate( CurvedAnimation( @@ -282,23 +276,10 @@ class _LevelUpPopupContentState extends State animation: _controller, builder: (_, __) => Row( children: [ - Expanded( - child: LayoutBuilder( - builder: (context, constraints) { - return LevelBar( - details: const LevelBarDetails( - fillColor: AppConfig.goldLight, - currentPoints: 0, - widthMultiplier: 1, - ), - progressBarDetails: ProgressBarDetails( - totalWidth: constraints.maxWidth * - progressAnimation.value, - height: 20, - borderColor: colorScheme.primary, - ), - ); - }, + const Expanded( + child: LevelPopupProgressBar( + height: 20, + duration: Duration(milliseconds: 1000), ), ), const SizedBox(width: 8), diff --git a/lib/pangea/analytics_summary/learning_progress_bar.dart b/lib/pangea/analytics_summary/learning_progress_bar.dart index b9f413520..7ee7bee2d 100644 --- a/lib/pangea/analytics_summary/learning_progress_bar.dart +++ b/lib/pangea/analytics_summary/learning_progress_bar.dart @@ -1,21 +1,20 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/analytics_summary/progress_bar/animated_progress_bar.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LearningProgressBar extends StatelessWidget { final int level; final int totalXP; - final double? height; + final double height; final bool loading; const LearningProgressBar({ required this.level, required this.totalXP, required this.loading, - this.height, + required this.height, super.key, }); @@ -30,16 +29,12 @@ class LearningProgressBar extends StatelessWidget { ), ); } - return ProgressBar( + + return AnimatedProgressBar( height: height, - levelBars: [ - LevelBarDetails( - fillColor: Theme.of(context).colorScheme.primary, - currentPoints: totalXP, - widthMultiplier: - MatrixState.pangeaController.getAnalytics.levelProgress, - ), - ], + widthPercent: MatrixState.pangeaController.getAnalytics.levelProgress, + barColor: AppConfig.goldLight, + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, ); } } diff --git a/lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart b/lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart deleted file mode 100644 index ccc966528..000000000 --- a/lib/pangea/analytics_summary/progress_bar/animated_level_dart.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/config/themes.dart'; - -class AnimatedLevelBar extends StatefulWidget { - final double height; - final double beginWidth; - final double endWidth; - final Color primaryColor; - - const AnimatedLevelBar({ - super.key, - required this.height, - required this.beginWidth, - required this.endWidth, - required this.primaryColor, - }); - - @override - AnimatedLevelBarState createState() => AnimatedLevelBarState(); -} - -class AnimatedLevelBarState extends State - with SingleTickerProviderStateMixin { - late AnimationController _controller; - - double get _beginWidth => - widget.beginWidth == 0 ? 0 : max(20, widget.beginWidth); - double get _endWidth => widget.endWidth == 0 ? 0 : max(20, widget.endWidth); - - /// Whether the animation has run for the first time during initState. Don't - /// want the animation to run when the widget mounts, only when points are gained. - bool _init = true; - - @override - void initState() { - super.initState(); - _controller = AnimationController( - vsync: this, - duration: FluffyThemes.animationDuration, - ); - - _controller.forward().then((_) => _init = false); - } - - @override - void didUpdateWidget(covariant AnimatedLevelBar oldWidget) { - super.didUpdateWidget(oldWidget); - if ((oldWidget.endWidth == 0 ? 0 : max(20, oldWidget.endWidth)) != - (widget.endWidth == 0 ? 0 : max(20, widget.endWidth))) { - _controller.reset(); - _controller.forward(); - } - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - Animation get _animation { - // If this is the first run of the animation, don't animate. This is just the widget mounting, - // not a points gain. This could instead be 'if going from 0 to a non-zero value', but that - // would remove the animation for first points gained. It would remove the need for a flag though. - if (_init) { - return Tween( - begin: _endWidth, - end: _endWidth, - ).animate(_controller); - } - - // animate the width of the bar - return Tween( - begin: _beginWidth, - end: _endWidth, - ).animate(_controller); - } - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: _animation, - builder: (context, child) { - return Stack( - children: [ - Container( - height: widget.height, - width: _animation.value, - decoration: BoxDecoration( - color: widget.primaryColor, - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - ), - ), - ], - ); - }, - ); - } -} diff --git a/lib/pangea/analytics_summary/progress_bar/animated_progress_bar.dart b/lib/pangea/analytics_summary/progress_bar/animated_progress_bar.dart new file mode 100644 index 000000000..94bf85c27 --- /dev/null +++ b/lib/pangea/analytics_summary/progress_bar/animated_progress_bar.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/themes.dart'; + +class AnimatedProgressBar extends StatelessWidget { + final double height; + final double widthPercent; + + final Color barColor; + final Color backgroundColor; + final Duration? duration; + + const AnimatedProgressBar({ + required this.height, + required this.widthPercent, + required this.barColor, + required this.backgroundColor, + this.duration, + super.key, + }); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + return Stack( + alignment: Alignment.centerLeft, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Container( + height: height, + width: constraints.maxWidth, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + color: backgroundColor, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: AnimatedContainer( + duration: duration ?? FluffyThemes.animationDuration, + height: height, + width: constraints.maxWidth * widthPercent, + decoration: BoxDecoration( + color: barColor, + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + ), + ), + ), + ], + ); + }, + ); + } +} diff --git a/lib/pangea/analytics_summary/progress_bar/level_bar.dart b/lib/pangea/analytics_summary/progress_bar/level_bar.dart deleted file mode 100644 index 3bf56c325..000000000 --- a/lib/pangea/analytics_summary/progress_bar/level_bar.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/animated_level_dart.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; - -class LevelBar extends StatefulWidget { - final LevelBarDetails details; - final ProgressBarDetails progressBarDetails; - - const LevelBar({ - super.key, - required this.details, - required this.progressBarDetails, - }); - - @override - LevelBarState createState() => LevelBarState(); -} - -class LevelBarState extends State { - double prevWidth = 0; - double get width => - widget.progressBarDetails.totalWidth * widget.details.widthMultiplier; - - @override - void didUpdateWidget(covariant LevelBar oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.details.currentPoints != widget.details.currentPoints) { - setState(() => prevWidth = width); - } - } - - @override - Widget build(BuildContext context) { - return AnimatedLevelBar( - height: widget.progressBarDetails.height, - beginWidth: prevWidth, - endWidth: width, - primaryColor: AppConfig.goldLight, - ); - } -} diff --git a/lib/pangea/analytics_summary/progress_bar/progress_bar.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar.dart deleted file mode 100644 index a257c1a21..000000000 --- a/lib/pangea/analytics_summary/progress_bar/progress_bar.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:fluffychat/pangea/analytics_summary/progress_bar/level_bar.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_background.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; - -// Provide an order list of level indicators, each with it's color -// and stream. Also provide an overall width and pointsPerLevel. - -class ProgressBar extends StatefulWidget { - final List levelBars; - final double? height; - - const ProgressBar({ - super.key, - required this.levelBars, - this.height, - }); - - @override - ProgressBarState createState() => ProgressBarState(); -} - -class ProgressBarState extends State { - double width = 0; - void setWidth(double newWidth) { - if (width != newWidth) { - setState(() => width = newWidth); - } - } - - get progressBarDetails => ProgressBarDetails( - totalWidth: width, - borderColor: Theme.of(context).colorScheme.secondaryContainer, - height: widget.height ?? 14, - ); - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - if (width != constraints.maxWidth) { - WidgetsBinding.instance.addPostFrameCallback( - (_) => setWidth(constraints.maxWidth), - ); - } - return Stack( - alignment: Alignment.centerLeft, - children: [ - ProgressBarBackground(details: progressBarDetails), - for (final levelBar in widget.levelBars) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 2), - child: LevelBar( - details: levelBar, - progressBarDetails: progressBarDetails, - ), - ), - ], - ); - }, - ); - } -} diff --git a/lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart deleted file mode 100644 index a3e320d07..000000000 --- a/lib/pangea/analytics_summary/progress_bar/progress_bar_background.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; - -class ProgressBarBackground extends StatelessWidget { - final ProgressBarDetails details; - - const ProgressBarBackground({ - super.key, - required this.details, - }); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 2), - child: Container( - height: details.height, - width: details.totalWidth, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: details.borderColor, - ), - ), - ); - } -} diff --git a/lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart b/lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart deleted file mode 100644 index a5196bf65..000000000 --- a/lib/pangea/analytics_summary/progress_bar/progress_bar_details.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'dart:ui'; - -class LevelBarDetails { - final Color fillColor; - final int currentPoints; - final double widthMultiplier; - - const LevelBarDetails({ - required this.fillColor, - required this.currentPoints, - required this.widthMultiplier, - }); -} - -class ProgressBarDetails { - final double totalWidth; - final Color borderColor; - final double height; - - const ProgressBarDetails({ - required this.totalWidth, - required this.borderColor, - this.height = 14, - }); -}