Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/src/confetti.dart
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,14 @@ class _ConfettiWidgetState extends State<ConfettiWidget>
}
}

@override
void didUpdateWidget(ConfettiWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.colors != oldWidget.colors) {
_particleSystem.colors = widget.colors;
}
}

@override
Widget build(BuildContext context) {
return LayoutBuilder(
Expand Down
4 changes: 3 additions & 1 deletion lib/src/particle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class ParticleSystem extends ChangeNotifier {
final double _blastDirection;
final BlastDirectionality _blastDirectionality;
final double _gravity;
final List<Color>? _colors;
List<Color>? _colors;
final Size _minimumSize;
final Size _maximumSize;
final double _particleDrag;
Expand All @@ -105,6 +105,8 @@ class ParticleSystem extends ChangeNotifier {
_setScreenBorderPositions();
}

set colors(List<Color>? colors) => _colors = colors;

void stopParticleEmission({bool clearAllParticles = false}) {
_particleSystemStatus = ParticleSystemStatus.stopped;
if (clearAllParticles) {
Expand Down
106 changes: 105 additions & 1 deletion test/confetti_test.dart
Original file line number Diff line number Diff line change
@@ -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', () {
Expand All @@ -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();
});
}