fix(player): 预热直出并与视频统一封面布局

This commit is contained in:
Zhou Weidong committed 2026-10-26 14:12:42 +08:00
1 parent a3a79f7068
commit 48b4e67d34
9 files changed
+119 -104

No files matched your search

+13 -17
View File
@@ -83,13 +83,9 @@ void main() {
);
expect(find.byKey(const Key('player-opening-poster')), findsOneWidget);
expect(
find.byKey(const Key('player-opening-poster-backdrop')),
findsOneWidget,
);
});
testWidgets('should_constrain_poster_inside_native_vertical_frame', (
testWidgets('should_use_surface_fit_without_extra_frame_constraint', (
tester,
) async {
await tester.pumpWidget(
@@ -100,23 +96,23 @@ void main() {
),
);
final stage = tester.widget<AspectRatio>(
find.byKey(const Key('player-opening-poster-stage')),
);
final poster = tester.widget<RemoteImage>(
find.byKey(const Key('player-opening-poster')),
);
final backdrop = tester.widget<RemoteImage>(
find.byKey(const Key('player-opening-poster-backdrop')),
expect(poster.fit, BoxFit.cover);
expect(find.byType(AspectRatio), findsNothing);
});
test('should_forward_video_fit_to_opening_frame', () {
final frame = playerOpeningFrame(
null,
posterUrl: 'https://cdn.test/poster.jpg',
fit: BoxFit.contain,
);
expect(stage.aspectRatio, closeTo(3 / 4, 0.001));
expect(poster.fit, BoxFit.cover);
expect(backdrop.fit, BoxFit.cover);
expect(
find.byKey(const Key('player-opening-poster-blur')),
findsOneWidget,
);
expect(frame, isA<PlayerOpeningFrame>());
expect((frame! as PlayerOpeningFrame).fit, BoxFit.contain);
});
testWidgets('should_reuse_decoded_sprite_when_parent_rebuilds', (
+28 -39
View File
@@ -30,7 +30,6 @@ void main() {
expect(find.byKey(const Key('player-opening-frame')), findsOneWidget);
expect(find.byKey(const Key('fake-opening')), findsOneWidget);
expect(_openingOpacity(tester), 1);
expect(_opacity(tester), 0);
});
@@ -49,7 +48,7 @@ void main() {
expect(find.byKey(const Key('player-opening-frame')), findsNothing);
});
testWidgets('should_cross_fade_video_over_opening_frame', (
testWidgets('should_show_cover_until_first_playback_frame', (
tester,
) async {
final controller = await _pumpSurface(
@@ -69,7 +68,6 @@ void main() {
await tester.pump();
expect(_opacity(tester), 0);
expect(_openingOpacity(tester), 1);
expect(find.byKey(const Key('player-opening-frame')), findsOneWidget);
controller.value = const VideoPlayerValue(
@@ -82,25 +80,36 @@ void main() {
await tester.pump();
expect(_opacity(tester), 1);
expect(find.byKey(const Key('player-opening-frame')), findsOneWidget);
expect(find.byKey(const Key('player-opening-frame')), findsNothing);
expect(
tester
.widget<AnimatedOpacity>(
find.byKey(const Key('player-video-opacity')),
)
.duration,
const Duration(milliseconds: 200),
Duration.zero,
);
await tester.pump(const Duration(milliseconds: 100));
final halfway = _fadeValue(tester);
expect(halfway, greaterThan(0));
expect(halfway, lessThan(1));
final openingHalfway = _openingFadeValue(tester);
expect(openingHalfway, greaterThan(0));
expect(openingHalfway, lessThan(1));
await tester.pump(const Duration(milliseconds: 100));
expect(_fadeValue(tester), 1);
expect(_openingFadeValue(tester), 0);
});
testWidgets('should_skip_cover_when_prewarmed_frame_is_available', (
tester,
) async {
await _pumpSurface(
tester,
openingFrame: const ColoredBox(color: Colors.red),
holdOpeningUntilFirstFrame: true,
preparedFrameAvailable: true,
value: const VideoPlayerValue(
duration: Duration(minutes: 1),
size: Size(1280, 720),
position: Duration.zero,
isInitialized: true,
isPlaying: false,
),
);
expect(find.byKey(const Key('player-opening-frame')), findsNothing);
expect(_opacity(tester), 1);
});
testWidgets('should_show_video_error_above_retained_fallback', (
@@ -147,6 +156,7 @@ void main() {
handoff: handoff,
videoUrl: current.dataSource,
theater: false,
openingFrame: const ColoredBox(color: Colors.red),
),
),
),
@@ -155,6 +165,7 @@ void main() {
await pump(previous);
expect(find.byKey(const Key('player-video-handoff')), findsOneWidget);
expect(find.byKey(const Key('player-opening-frame')), findsNothing);
expect(_opacity(tester), 1);
await pump(null);
@@ -168,6 +179,7 @@ Future<VideoPlayerController> _pumpSurface(
VideoPlayerValue? value,
Widget? openingFrame,
bool holdOpeningUntilFirstFrame = false,
bool preparedFrameAvailable = false,
}) async {
final controller = VideoPlayerController.networkUrl(
Uri.parse('http://192.168.31.187:8081/files/video.mp4'),
@@ -183,6 +195,7 @@ Future<VideoPlayerController> _pumpSurface(
theater: false,
openingFrame: openingFrame,
holdOpeningUntilFirstFrame: holdOpeningUntilFirstFrame,
preparedFrameAvailable: preparedFrameAvailable,
),
),
),
@@ -202,27 +215,3 @@ double _opacity(WidgetTester tester) {
.widget<AnimatedOpacity>(find.byKey(const Key('player-video-opacity')))
.opacity;
}
double _openingOpacity(WidgetTester tester) {
return tester
.widget<AnimatedOpacity>(
find.byKey(const Key('player-opening-frame')),
)
.opacity;
}
double _fadeValue(WidgetTester tester) {
final fade = find.descendant(
of: find.byKey(const Key('player-video-opacity')),
matching: find.byType(FadeTransition),
);
return tester.widget<FadeTransition>(fade).opacity.value;
}
double _openingFadeValue(WidgetTester tester) {
final fade = find.descendant(
of: find.byKey(const Key('player-opening-frame')),
matching: find.byType(FadeTransition),
);
return tester.widget<FadeTransition>(fade).opacity.value;
}