refactor: improve typing indicator in assistant message widget

- Replaced the previous gradient-based typing indicator with a more dynamic three-dot animation.
- Simplified the animation logic for the typing indicator, enhancing visual feedback and responsiveness.
- Adjusted the layout to ensure proper spacing and prevent clipping during animations.
- Cleaned up the code for better readability and maintainability.
This commit is contained in:
cogwheel0
2025-10-01 01:50:36 +05:30
parent 5a4021aaa9
commit 3faac9f16b

View File

@@ -970,77 +970,57 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
Widget _buildTypingIndicator() { Widget _buildTypingIndicator() {
final theme = context.conduitTheme; final theme = context.conduitTheme;
final gradient = LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
theme.surfaceBackground.withValues(alpha: 0.0),
theme.surfaceContainer.withValues(alpha: 0.9),
],
);
final haloColor = theme.textSecondary.withValues(alpha: 0.18);
final dotColor = theme.textSecondary.withValues(alpha: 0.75); final dotColor = theme.textSecondary.withValues(alpha: 0.75);
const double dotSize = 8.0; const double dotSize = 8.0;
final min = AnimationValues.typingIndicatorScale; const double dotSpacing = 6.0;
const int numberOfDots = 3;
final dot = // Create three dots with staggered animations
Container( final dots = List.generate(numberOfDots, (index) {
final delay = Duration(milliseconds: 150 * index);
return Container(
width: dotSize, width: dotSize,
height: dotSize, height: dotSize,
decoration: BoxDecoration( decoration: BoxDecoration(color: dotColor, shape: BoxShape.circle),
color: dotColor,
shape: BoxShape.circle,
),
) )
.animate(onPlay: (controller) => controller.repeat()) .animate(onPlay: (controller) => controller.repeat())
.then(delay: delay)
.fadeIn(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
)
.scale( .scale(
duration: AnimationDuration.typingIndicator, duration: const Duration(milliseconds: 600),
curve: AnimationCurves.typingIndicator, curve: Curves.easeInOut,
begin: Offset(min, min), begin: const Offset(0.4, 0.4),
end: const Offset(1, 1), end: const Offset(1, 1),
) )
.then(delay: AnimationDelay.typingDelay) .then()
.scale( .scale(
duration: AnimationDuration.typingIndicator, duration: const Duration(milliseconds: 600),
curve: AnimationCurves.typingIndicator, curve: Curves.easeInOut,
begin: const Offset(1, 1), begin: const Offset(1.2, 1.2),
end: Offset(min, min), end: const Offset(0.5, 0.5),
); );
});
return Column( return Padding(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.symmetric(vertical: Spacing.sm),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [ children: [
const SizedBox(height: Spacing.md), // Add left padding to prevent clipping when dots scale up
Padding( const SizedBox(width: dotSize * 0.2),
padding: const EdgeInsets.only(left: 4, bottom: 4), for (int i = 0; i < numberOfDots; i++) ...[
child: Container( dots[i],
decoration: BoxDecoration( if (i < numberOfDots - 1) const SizedBox(width: dotSpacing),
gradient: gradient, ],
borderRadius: BorderRadius.circular(16), // Add right padding to prevent clipping when dots scale up
), const SizedBox(width: dotSize * 0.2),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: SizedBox(
height: dotSize * 2,
width: dotSize * 2,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: dotSize * 2,
height: dotSize * 2,
decoration: BoxDecoration(
color: haloColor,
shape: BoxShape.circle,
),
),
dot,
], ],
), ),
),
),
),
],
); );
} }