merge: 合并 K40-A 播放加载修复

This commit is contained in:
Zhou Weidong committed 2026-10-20 15:59:32 +08:00
commit 1eea9fafe7
2 files changed
+86 -10

No files matched your search

+41 -7
View File
@@ -20,6 +20,7 @@ import '../../core/theme/app_colors.dart';
import '../../core/theme/app_theme.dart';
import '../../core/widgets/auth_gate.dart';
import '../../core/widgets/download_action.dart';
import '../../core/widgets/remote_image.dart';
import '../../l10n/app_localizations.dart';
import 'player_binding.dart';
import 'player_logic.dart';
@@ -298,11 +299,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
return Stack(
fit: StackFit.expand,
children: [
if (!ready)
const ColoredBox(
key: Key('player-fallback-background'),
color: Colors.black,
),
if (!ready) _PlayerFallbackBackground(posterUrl: drama.posterUrl),
?video,
if (widget.homeMode && _chromeVisible && !logic.chromeHidden)
Positioned.fill(
@@ -316,7 +313,10 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
// 票据三态之一:起播前正在向后端要签名地址
if (selected && logic.ticketLoading)
const Center(
child: CircularProgressIndicator(color: AppColors.blueSoft),
child: CircularProgressIndicator(
key: Key('player-ticket-loading'),
color: AppColors.blue,
),
),
// 票据三态之二:拿票失败(断网/服务异常)→ 可重试,不假装在加载
if (selected && !logic.ticketLoading && logic.ticketError != null)
@@ -348,7 +348,10 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
),
if (selected && logic.session.loading)
const Center(
child: CircularProgressIndicator(color: AppColors.blueSoft),
child: CircularProgressIndicator(
key: Key('player-session-loading'),
color: AppColors.blue,
),
),
if (selected && !ready && logic.session.error != null)
Center(
@@ -550,3 +553,34 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
);
}
}
class _PlayerFallbackBackground extends StatelessWidget {
const _PlayerFallbackBackground({required this.posterUrl});
final String posterUrl;
@override
Widget build(BuildContext context) {
if (posterUrl.trim().isEmpty) {
return const ColoredBox(
key: Key('player-fallback-background'),
color: Colors.black,
);
}
return Stack(
key: const Key('player-fallback-background'),
fit: StackFit.expand,
children: [
RemoteImage(
posterUrl,
key: const Key('player-fallback-cover'),
fit: BoxFit.cover,
),
const ColoredBox(
key: Key('player-fallback-scrim'),
color: Color(0x66000000),
),
],
);
}
}
+45 -3
View File
@@ -49,6 +49,26 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('should_fall_back_to_black_when_poster_is_empty', (tester) async {
await _pumpApp(
tester,
catalog: FakeCatalogRepository(dramas: const [_noCoverDrama]),
);
await _openSeriesPlayer(
tester,
cardKey: const Key('home-drama-card-no-cover-demo'),
);
expect(
tester
.widget<ColoredBox>(
find.byKey(const Key('player-fallback-background')),
)
.color,
Colors.black,
);
});
testWidgets('should_show_center_toggle_only_when_paused', (tester) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
@@ -283,9 +303,14 @@ void main() {
);
expect(find.byKey(const Key('player-background')), findsNothing);
final fallback = find.byKey(const Key('player-fallback-background'));
if (fallback.evaluate().isNotEmpty) {
expect(tester.widget<ColoredBox>(fallback).color, Colors.black);
}
expect(fallback, findsOneWidget);
expect(find.byKey(const Key('player-fallback-cover')), findsOneWidget);
expect(
tester
.widget<ColoredBox>(find.byKey(const Key('player-fallback-scrim')))
.color,
const Color(0x66000000),
);
expect(
tester
.widget<Scaffold>(find.byKey(const Key('player-scaffold')))
@@ -1024,3 +1049,20 @@ const _lockedDrama = Drama(
),
],
);
const _noCoverDrama = Drama(
id: 'no-cover-demo',
title: 'No Cover Demo',
synopsis: 'No cover synopsis',
posterUrl: '',
detailLoaded: true,
episodes: [
Episode(
id: 'no-cover-demo-1',
number: 1,
title: 'No Cover Episode',
isFree: true,
videoUrl: 'https://example.test/no-cover-demo-1.mp4',
),
],
);