fix(home): 频道切换用封面过渡

This commit is contained in:
Zhou Weidong committed 2026-10-21 18:06:09 +08:00
1 parent 838ca2ce2a
commit c9adf8b399
5 files changed
+111 -19

No files matched your search

+51 -1
View File
@@ -7,9 +7,11 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/app.dart';
import 'package:fruitshorts/core/data/models/feed_page.dart';
import 'package:fruitshorts/core/data/models/player_port.dart';
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
import 'package:fruitshorts/core/data/services/playback_session.dart';
import 'package:fruitshorts/pages/home/home_feed_channel.dart';
import 'package:fruitshorts/pages/player/player_view.dart';
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
@@ -120,6 +122,37 @@ void main() {
expect(player.homeMode, isFalse);
});
testWidgets('should_hide_session_loading_only_on_home_feed', (tester) async {
final players = <_PendingPlayer>[];
await _pumpApp(
tester,
playerFactory: (_) {
final player = _PendingPlayer();
players.add(player);
return player;
},
);
expect(find.byType(PlayerPage), findsOneWidget);
expect(find.byKey(const Key('player-session-loading')), findsNothing);
await tester.tap(find.byKey(const Key('home-feed-full-series')));
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
expect(find.byKey(const Key('player-session-loading')), findsOneWidget);
for (var round = 0; round < 6; round++) {
for (final player in players) {
if (!player.initialized.isCompleted) {
player.initialized.complete();
}
}
await tester.pump();
}
await tester.pumpAndSettle();
});
testWidgets('should_switch_to_anime_channel', (tester) async {
await _pumpApp(tester);
@@ -489,6 +522,7 @@ Future<void> _pumpApp(
WidgetTester tester, {
Size size = const Size(390, 844),
FakeCatalogRepository? catalog,
PlayerFactory? playerFactory,
}) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1;
@@ -497,7 +531,7 @@ Future<void> _pumpApp(
final repository = catalog ?? FakeCatalogRepository();
await tester.pumpWidget(
LumaDramaApp(
playerFactory: createWidgetPlayer,
playerFactory: playerFactory ?? createWidgetPlayer,
catalogRepository: repository,
categoryRepository: FakeCategoryRepository(catalog: repository),
watchHistoryRepository: InMemoryWatchHistoryRepository(),
@@ -542,3 +576,19 @@ class _EmptyAnimeCatalog extends FakeCatalogRepository {
return super.fetchFeed(types: types, cursor: cursor, size: size);
}
}
class _PendingPlayer implements PlayerPort {
final initialized = Completer<void>();
@override
Future<void> initialize() => initialized.future;
@override
Future<void> play() async {}
@override
Future<void> pause() async {}
@override
Future<void> dispose() async {}
}
+5 -12
View File
@@ -131,18 +131,12 @@ void main() {
expect(player.playing, isTrue);
});
testWidgets('should_keep_video_surface_background_black', (tester) async {
testWidgets('should_show_poster_before_video_first_frame', (tester) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
expect(
tester
.widget<ColoredBox>(
find.byKey(const Key('player-fallback-background')),
)
.color,
Colors.black,
);
expect(find.byKey(const Key('player-video-poster')), findsOneWidget);
expect(find.byKey(const Key('player-fallback-background')), findsNothing);
expect(find.byKey(const Key('player-fallback-cover')), findsNothing);
expect(find.byKey(const Key('player-fallback-scrim')), findsNothing);
});
@@ -471,9 +465,8 @@ void main() {
find.byKey(const Key('player-interaction-rail')),
);
expect(find.byKey(const Key('player-background')), findsNothing);
final fallback = find.byKey(const Key('player-fallback-background'));
expect(fallback, findsOneWidget);
expect(tester.widget<ColoredBox>(fallback).color, Colors.black);
expect(find.byKey(const Key('player-video-poster')), findsOneWidget);
expect(find.byKey(const Key('player-fallback-background')), findsNothing);
expect(find.byKey(const Key('player-fallback-cover')), findsNothing);
expect(find.byKey(const Key('player-fallback-scrim')), findsNothing);
expect(
@@ -7,6 +7,24 @@ import 'package:video_player/video_player.dart';
import 'package:fruitshorts/pages/player/widgets/player_video_surface.dart';
void main() {
testWidgets('should_show_poster_when_controller_is_missing', (tester) async {
await _pumpBareSurface(tester, posterUrl: '/files/poster.png');
expect(find.byKey(const Key('player-video-poster')), findsOneWidget);
expect(find.byKey(const Key('player-fallback-background')), findsNothing);
expect(_opacity(tester), 0);
});
testWidgets('should_keep_black_fallback_when_poster_is_empty', (
tester,
) async {
await _pumpBareSurface(tester);
expect(find.byKey(const Key('player-video-poster')), findsNothing);
expect(_fallbackColor(tester), Colors.black);
expect(_opacity(tester), 0);
});
testWidgets('should_keep_fallback_visible_before_video_is_ready', (
tester,
) async {
@@ -96,6 +114,25 @@ Future<VideoPlayerController> _pumpSurface(
return controller;
}
Future<void> _pumpBareSurface(
WidgetTester tester, {
String posterUrl = '',
}) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: PlayerVideoSurface(
controller: null,
videoUrl: '',
posterUrl: posterUrl,
theater: false,
onTap: () {},
),
),
),
);
}
Color _fallbackColor(WidgetTester tester) {
return tester
.widget<ColoredBox>(find.byKey(const Key('player-fallback-background')))