feat(player): animate circular feedback on transport buttons

This commit is contained in:
zarzet committed 2026-09-26 03:50:52 +07:00
1 parent 7d7716cd6f
commit 607f9c440b
2 files changed
+92 -2

No files matched your search

+47
View File
@@ -27,6 +27,18 @@ void main() {
),
);
double feedbackOpacity(WidgetTester tester) {
final feedback = tester.widget<DecoratedBox>(
find
.ancestor(
of: find.byType(IconButton),
matching: find.byType(DecoratedBox),
)
.first,
);
return (feedback.decoration as BoxDecoration).color!.a;
}
testWidgets('press feedback keeps the tap target fixed and cancels safely', (
tester,
) async {
@@ -36,15 +48,18 @@ void main() {
final icon = find.byIcon(CupertinoIcons.play_fill);
final bounds = tester.getRect(button);
final iconBounds = tester.getRect(icon);
expect(feedbackOpacity(tester), 0);
final press = await tester.startGesture(bounds.center);
await tester.pump(const Duration(milliseconds: 100));
await tester.pump(const Duration(milliseconds: 200));
expect(tester.getRect(icon).width, lessThan(iconBounds.width));
expect(tester.getRect(button), bounds);
expect(feedbackOpacity(tester), closeTo(0.14, 0.001));
await press.up();
await tester.pumpAndSettle();
expect(calls, 1);
expect(tester.getRect(icon), iconBounds);
expect(feedbackOpacity(tester), 0);
final cancelled = await tester.startGesture(bounds.center);
await tester.pump(const Duration(milliseconds: 100));
@@ -52,8 +67,40 @@ void main() {
await tester.pumpAndSettle();
expect(calls, 1);
expect(tester.getRect(icon), iconBounds);
expect(feedbackOpacity(tester), 0);
});
for (final icon in [
CupertinoIcons.play_fill,
CupertinoIcons.pause_fill,
CupertinoIcons.forward_fill,
CupertinoIcons.backward_fill,
]) {
testWidgets('quick tap on $icon fades a circular highlight in and out', (
tester,
) async {
var calls = 0;
await pumpButton(tester, icon: icon, onPressed: () => calls++);
final button = find.byType(IconButton);
final bounds = tester.getRect(button);
await tester.tap(button);
expect(calls, 1);
await tester.pump();
await tester.pump(const Duration(milliseconds: 50));
final entering = feedbackOpacity(tester);
expect(entering, greaterThan(0));
await tester.pump(const Duration(milliseconds: 60));
final peak = feedbackOpacity(tester);
expect(peak, greaterThan(entering));
await tester.pump(const Duration(milliseconds: 220));
expect(feedbackOpacity(tester), lessThan(peak));
expect(tester.getRect(button), bounds);
await tester.pumpAndSettle();
expect(feedbackOpacity(tester), 0);
expect(calls, 1);
});
}
for (final icon in [
CupertinoIcons.forward_fill,
CupertinoIcons.backward_fill,