From a79b72ffe9056f6713a24474790f6de2142a4788 Mon Sep 17 00:00:00 2001 From: avashilling <165050625+avashilling@users.noreply.github.com> Date: Thu, 9 Oct 2025 13:01:50 -0400 Subject: [PATCH] change seed to new vocab bubble (#4305) * change seed to new vocab bubble and tweak the animation to fade in, then rise/fade out since this looks better than spinning in. * formatting --------- Co-authored-by: ggurdin --- .../widgets/word_zoom/new_word_overlay.dart | 114 ++++++++++++------ 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/lib/pangea/toolbar/widgets/word_zoom/new_word_overlay.dart b/lib/pangea/toolbar/widgets/word_zoom/new_word_overlay.dart index 82678805e..ed0180347 100644 --- a/lib/pangea/toolbar/widgets/word_zoom/new_word_overlay.dart +++ b/lib/pangea/toolbar/widgets/word_zoom/new_word_overlay.dart @@ -1,10 +1,8 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; -import 'package:fluffychat/config/themes.dart'; +import 'package:material_symbols_icons/symbols.dart'; + import 'package:fluffychat/pangea/common/utils/overlay.dart'; -import 'package:fluffychat/pangea/constructs/construct_level_enum.dart'; import 'package:fluffychat/pangea/message_token_text/tokens_util.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -27,30 +25,46 @@ class NewWordOverlay extends StatefulWidget { class _NewWordOverlayState extends State with TickerProviderStateMixin { AnimationController? _controller; - Animation? _xpScaleAnim; - Animation? _fadeAnim; + Animation? _opacityAnim; Animation? _moveAnim; - bool columnMode = false; - - Widget? get svg => ConstructLevelEnum.seeds.icon(); + Animation? _backgroundFadeAnim; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, - duration: const Duration(milliseconds: 1850), + duration: const Duration(milliseconds: 2000), ); - _xpScaleAnim = CurvedAnimation( - parent: _controller!, - curve: const Interval(0.0, 0.5, curve: Curves.easeInOut), - ); + _opacityAnim = TweenSequence([ + TweenSequenceItem( + tween: Tween(begin: 0.0, end: 1.0) + .chain(CurveTween(curve: Curves.easeIn)), + weight: 25, + ), + TweenSequenceItem( + tween: ConstantTween(1.0), + weight: 25, + ), + TweenSequenceItem( + tween: Tween(begin: 1.0, end: 0.0) + .chain(CurveTween(curve: Curves.easeOut)), + weight: 50, + ), + ]).animate(_controller!); - _fadeAnim = CurvedAnimation( - parent: _controller!, - curve: const Interval(0.5, 1.0, curve: Curves.easeOut), - ); + _backgroundFadeAnim = TweenSequence([ + TweenSequenceItem( + tween: ConstantTween(1.0), + weight: 50, + ), + TweenSequenceItem( + tween: Tween(begin: 1.0, end: 0.0) + .chain(CurveTween(curve: Curves.easeOut)), + weight: 50, + ), + ]).animate(_controller!); _moveAnim = CurvedAnimation( parent: _controller!, @@ -58,7 +72,6 @@ class _NewWordOverlayState extends State ); WidgetsBinding.instance.addPostFrameCallback((_) { - columnMode = FluffyThemes.isColumnMode(context); _showFlyingWidget(); _controller?.forward().then((_) { TokensUtil.clearNewTokenCache(); @@ -75,10 +88,7 @@ class _NewWordOverlayState extends State } void _showFlyingWidget() { - if (_controller == null || - _xpScaleAnim == null || - _fadeAnim == null || - _moveAnim == null) { + if (_controller == null || _opacityAnim == null || _moveAnim == null) { return; } @@ -86,32 +96,22 @@ class _NewWordOverlayState extends State context: context, closePrevOverlay: false, ignorePointer: true, - offset: const Offset(0, 65), + offset: const Offset(0, 45), targetAnchor: Alignment.center, overlayKey: widget.transformTargetId, transformTargetId: widget.transformTargetId, child: AnimatedBuilder( animation: _controller!, builder: (context, child) { - final scale = _xpScaleAnim!.value; - final fade = 1.0 - (_fadeAnim!.value); + final opacity = _opacityAnim!.value; final move = _moveAnim!.value; - - final seedSize = 75 * scale; final moveY = -move * 60; return Transform.translate( offset: Offset(0, moveY), child: Opacity( - opacity: fade, - child: Transform.rotate( - angle: scale * 2 * pi, - child: SizedBox( - width: seedSize, - height: seedSize, - child: svg ?? const SizedBox(), - ), - ), + opacity: opacity, + child: const NewVocabBubble(), ), ); }, @@ -130,7 +130,7 @@ class _NewWordOverlayState extends State top: 50, bottom: 5, child: Opacity( - opacity: 1 - _fadeAnim!.value, + opacity: _backgroundFadeAnim!.value, child: Container( height: double.infinity, width: double.infinity, @@ -142,3 +142,41 @@ class _NewWordOverlayState extends State ); } } + +class NewVocabBubble extends StatelessWidget { + const NewVocabBubble({super.key}); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Container( + decoration: BoxDecoration( + color: theme.colorScheme.surfaceContainerHighest, + borderRadius: const BorderRadius.all(Radius.circular(16.0)), + ), + padding: const EdgeInsets.symmetric( + vertical: 8.0, + horizontal: 16.0, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Symbols.toys_and_games, + color: theme.colorScheme.primary, + size: 24, + ), + const SizedBox(width: 4.0), + Text( + "+ 1", + style: TextStyle( + color: theme.colorScheme.primary, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + ], + ), + ); + } +}