diff --git a/lib/src/confetti.dart b/lib/src/confetti.dart index 29c3477..c39a49c 100644 --- a/lib/src/confetti.dart +++ b/lib/src/confetti.dart @@ -343,6 +343,14 @@ class _ConfettiWidgetState extends State } } + @override + void didUpdateWidget(ConfettiWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.colors != oldWidget.colors) { + _particleSystem.colors = widget.colors; + } + } + @override Widget build(BuildContext context) { return LayoutBuilder( diff --git a/lib/src/particle.dart b/lib/src/particle.dart index 3f55b95..b19c09e 100644 --- a/lib/src/particle.dart +++ b/lib/src/particle.dart @@ -80,7 +80,7 @@ class ParticleSystem extends ChangeNotifier { final double _blastDirection; final BlastDirectionality _blastDirectionality; final double _gravity; - final List? _colors; + List? _colors; final Size _minimumSize; final Size _maximumSize; final double _particleDrag; @@ -105,6 +105,8 @@ class ParticleSystem extends ChangeNotifier { _setScreenBorderPositions(); } + set colors(List? colors) => _colors = colors; + void stopParticleEmission({bool clearAllParticles = false}) { _particleSystemStatus = ParticleSystemStatus.stopped; if (clearAllParticles) { diff --git a/test/confetti_test.dart b/test/confetti_test.dart index 79440e5..6b8b65a 100644 --- a/test/confetti_test.dart +++ b/test/confetti_test.dart @@ -1,6 +1,9 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'dart:math'; import 'package:confetti/confetti.dart'; +import 'package:confetti/src/particle.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; void main() { group('ConfettiController', () { @@ -20,4 +23,105 @@ void main() { throwsAssertionError); }); }); + + group('ParticleSystem', () { + test('updates colors via setter', () { + final system = ParticleSystem( + emissionFrequency: 0.02, + numberOfParticles: 10, + maxBlastForce: 20, + minBlastForce: 5, + gravity: 0.2, + blastDirection: pi, + blastDirectionality: BlastDirectionality.directional, + colors: const [Colors.blue], + minimumSize: const Size(20, 10), + maximumSize: const Size(30, 15), + particleDrag: 0.05, + ); + + system.colors = const [Colors.red]; + + // Start emission to generate particles + system.startParticleEmission(); + system.screenSize = const Size(400, 800); + system.update(0.016); + + final particles = system.particles; + expect(particles.isNotEmpty, isTrue); + // All generated particles should use the updated color (red, not blue) + for (final particle in particles) { + expect(particle.color, equals(Colors.red)); + } + }); + + test('colors setter affects newly generated particles', () { + final system = ParticleSystem( + emissionFrequency: 0.02, + numberOfParticles: 10, + maxBlastForce: 20, + minBlastForce: 5, + gravity: 0.2, + blastDirection: pi, + blastDirectionality: BlastDirectionality.directional, + colors: const [Colors.blue], + minimumSize: const Size(20, 10), + maximumSize: const Size(30, 15), + particleDrag: 0.05, + ); + + system.startParticleEmission(); + system.screenSize = const Size(400, 800); + system.update(0.016); + + // First batch should be blue + for (final particle in system.particles) { + expect(particle.color, equals(Colors.blue)); + } + + // Update colors and generate new particles + system.colors = const [Colors.green]; + system.stopParticleEmission(clearAllParticles: true); + system.update(0.016); // finish + + system.startParticleEmission(); + system.update(0.016); + + // New batch should be green + for (final particle in system.particles) { + expect(particle.color, equals(Colors.green)); + } + }); + }); + + testWidgets('ConfettiWidget rebuilds with updated colors', (tester) async { + final controller = ConfettiController(); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: ConfettiWidget( + confettiController: controller, + colors: const [Colors.blue], + ), + ), + ), + ); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: ConfettiWidget( + confettiController: controller, + colors: const [Colors.red], + ), + ), + ), + ); + + // Widget should not throw when rebuilt with new colors + expect(tester.takeException(), isNull); + + controller.dispose(); + }); }