fix(player): 修正飘心Overlay生命周期
This commit is contained in:
1 parent
a7d01e0306
commit
c0f65042e6
4 files changed
+184
-28
No files matched your search
@@ -7,6 +7,7 @@ import 'package:fruitshorts/core/theme/app_theme.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/home_feed_overlay.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_double_tap_hearts.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_heart_overlay_scope.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/player_tap_gesture_region.dart';
|
||||
|
||||
import '../support/fake_catalog.dart';
|
||||
@@ -155,9 +156,7 @@ void main() {
|
||||
expect(elapsedMs, greaterThanOrEqualTo(1500));
|
||||
});
|
||||
|
||||
testWidgets('heart burst is cleaned up when gesture region is disposed', (
|
||||
tester,
|
||||
) async {
|
||||
testWidgets('heart burst starts at tapped location', (tester) async {
|
||||
final key = GlobalKey<_HarnessState>();
|
||||
final clock = _TestClock();
|
||||
await _pumpHarness(
|
||||
@@ -183,10 +182,62 @@ void main() {
|
||||
.distance,
|
||||
lessThanOrEqualTo(1),
|
||||
);
|
||||
});
|
||||
|
||||
await tester.pumpWidget(const SizedBox.shrink());
|
||||
await tester.pump();
|
||||
expect(find.byType(PlayerDoubleTapHeartBurst), findsNothing);
|
||||
testWidgets('heart burst survives gesture region disposal', (tester) async {
|
||||
final logs = <String>[];
|
||||
final originalDebugPrint = debugPrint;
|
||||
debugPrint = (message, {wrapWidth}) {
|
||||
if (message != null) logs.add(message);
|
||||
};
|
||||
var elapsedMs = 0;
|
||||
try {
|
||||
final key = GlobalKey<_RemovableGestureHarnessState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(home: _RemovableGestureHarness(key: key)),
|
||||
);
|
||||
const tapPosition = Offset(120, 220);
|
||||
|
||||
await tester.tapAt(tapPosition);
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
await tester.tapAt(tapPosition);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
|
||||
final burstFinder = find.byType(PlayerDoubleTapHeartBurst);
|
||||
expect(burstFinder, findsOneWidget);
|
||||
key.currentState!.removeGesture();
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('removable-tap-gesture')), findsNothing);
|
||||
expect(burstFinder, findsOneWidget);
|
||||
|
||||
elapsedMs = 100;
|
||||
while (burstFinder.evaluate().isNotEmpty && elapsedMs < 2000) {
|
||||
await tester.pump(const Duration(milliseconds: 16));
|
||||
elapsedMs += 16;
|
||||
}
|
||||
expect(burstFinder, findsNothing);
|
||||
} finally {
|
||||
debugPrint = originalDebugPrint;
|
||||
}
|
||||
|
||||
expect(elapsedMs, greaterThanOrEqualTo(1500));
|
||||
expect(
|
||||
logs.any(
|
||||
(line) =>
|
||||
line.contains('phase=heart-burst-complete') &&
|
||||
line.contains('configuredMs=1590'),
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
logs.any(
|
||||
(line) =>
|
||||
line.contains('phase=heart-burst-dispose') &&
|
||||
line.contains('completed=1'),
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('multiple heart bursts run independently', (tester) async {
|
||||
@@ -328,6 +379,55 @@ class _HarnessState extends State<_Harness> {
|
||||
}
|
||||
}
|
||||
|
||||
class _RemovableGestureHarness extends StatefulWidget {
|
||||
const _RemovableGestureHarness({super.key});
|
||||
|
||||
@override
|
||||
State<_RemovableGestureHarness> createState() =>
|
||||
_RemovableGestureHarnessState();
|
||||
}
|
||||
|
||||
class _RemovableGestureHarnessState extends State<_RemovableGestureHarness> {
|
||||
final PlayerHeartOverlayController _heartController =
|
||||
PlayerHeartOverlayController();
|
||||
bool _showGesture = true;
|
||||
|
||||
void removeGesture() => setState(() => _showGesture = false);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_heartController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PlayerHeartOverlayScope(
|
||||
controller: _heartController,
|
||||
child: Scaffold(
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (_showGesture)
|
||||
Positioned.fill(
|
||||
child: PlayerTapGestureRegion(
|
||||
key: const Key('removable-tap-gesture'),
|
||||
gestureKey: const Key('removable-gesture'),
|
||||
enabled: true,
|
||||
doubleTapEnabled: true,
|
||||
onSingleTap: () {},
|
||||
onDoubleTapLike: (_) {},
|
||||
onLongPressStart: (_, _) {},
|
||||
onInteractionEnd: () {},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TestClock {
|
||||
DateTime _now = DateTime(2026, 10, 22, 12);
|
||||
|
||||
|
||||
Reference in new issue
Block a user