fix(flutter): 收紧播放页底部与互动栏

This commit is contained in:
Zhou Weidong committed 2026-10-20 11:12:12 +08:00
1 parent 7b4a792c12
commit cf93d8d794
10 files changed
+122 -195

No files matched your search

-2
View File
@@ -592,9 +592,7 @@
"unlockMethodsVary": "Available unlock methods vary by title.", "unlockMethodsVary": "Available unlock methods vary by title.",
"unlockEpisode": "Unlock this episode", "unlockEpisode": "Unlock this episode",
"language": "Language", "language": "Language",
"fullScreenWatch": "Full screen",
"freeWatch": "Free watch", "freeWatch": "Free watch",
"showMore": "More",
"qualityUnavailable": "Unavailable", "qualityUnavailable": "Unavailable",
"notInterested": "Not interested", "notInterested": "Not interested",
"clearPlayback": "Clear-screen playback", "clearPlayback": "Clear-screen playback",
-2
View File
@@ -590,9 +590,7 @@
"unlockMethodsVary": "Metode pembukaan tersedia dapat berbeda per judul.", "unlockMethodsVary": "Metode pembukaan tersedia dapat berbeda per judul.",
"unlockEpisode": "Buka episode ini", "unlockEpisode": "Buka episode ini",
"language": "Bahasa", "language": "Bahasa",
"fullScreenWatch": "Layar penuh",
"freeWatch": "Tonton gratis", "freeWatch": "Tonton gratis",
"showMore": "Selengkapnya",
"qualityUnavailable": "Tidak tersedia", "qualityUnavailable": "Tidak tersedia",
"notInterested": "Tidak tertarik", "notInterested": "Tidak tertarik",
"clearPlayback": "Putar tanpa kontrol", "clearPlayback": "Putar tanpa kontrol",
-12
View File
@@ -2638,24 +2638,12 @@ abstract class AppLocalizations {
/// **'Language'** /// **'Language'**
String get language; String get language;
/// No description provided for @fullScreenWatch.
///
/// In en, this message translates to:
/// **'Full screen'**
String get fullScreenWatch;
/// No description provided for @freeWatch. /// No description provided for @freeWatch.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Free watch'** /// **'Free watch'**
String get freeWatch; String get freeWatch;
/// No description provided for @showMore.
///
/// In en, this message translates to:
/// **'More'**
String get showMore;
/// No description provided for @qualityUnavailable. /// No description provided for @qualityUnavailable.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
-6
View File
@@ -1368,15 +1368,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get language => 'Language'; String get language => 'Language';
@override
String get fullScreenWatch => 'Full screen';
@override @override
String get freeWatch => 'Free watch'; String get freeWatch => 'Free watch';
@override
String get showMore => 'More';
@override @override
String get qualityUnavailable => 'Unavailable'; String get qualityUnavailable => 'Unavailable';
-6
View File
@@ -1368,15 +1368,9 @@ class AppLocalizationsId extends AppLocalizations {
@override @override
String get language => 'Bahasa'; String get language => 'Bahasa';
@override
String get fullScreenWatch => 'Layar penuh';
@override @override
String get freeWatch => 'Tonton gratis'; String get freeWatch => 'Tonton gratis';
@override
String get showMore => 'Selengkapnya';
@override @override
String get qualityUnavailable => 'Tidak tersedia'; String get qualityUnavailable => 'Tidak tersedia';
-6
View File
@@ -1344,15 +1344,9 @@ class AppLocalizationsZh extends AppLocalizations {
@override @override
String get language => '语言'; String get language => '语言';
@override
String get fullScreenWatch => '全屏观看';
@override @override
String get freeWatch => '免费观看'; String get freeWatch => '免费观看';
@override
String get showMore => '展开';
@override @override
String get qualityUnavailable => '暂不可用'; String get qualityUnavailable => '暂不可用';
-2
View File
@@ -552,9 +552,7 @@
"unlockMethodsVary": "具体解锁方式以作品而定。", "unlockMethodsVary": "具体解锁方式以作品而定。",
"unlockEpisode": "解锁本集", "unlockEpisode": "解锁本集",
"language": "语言", "language": "语言",
"fullScreenWatch": "全屏观看",
"freeWatch": "免费观看", "freeWatch": "免费观看",
"showMore": "展开",
"qualityUnavailable": "暂不可用", "qualityUnavailable": "暂不可用",
"notInterested": "不感兴趣", "notInterested": "不感兴趣",
"clearPlayback": "清屏播放", "clearPlayback": "清屏播放",
+13 -73
View File
@@ -1,8 +1,6 @@
// Author: fruit.com.cn // Author: fruit.com.cn
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import '../../../core/formatting/localized_content.dart'; import '../../../core/formatting/localized_content.dart';
import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_dimens.dart'; import '../../../core/theme/app_dimens.dart';
@@ -14,11 +12,10 @@ import 'seek_progress_bar.dart';
part 'player_overlay_parts.dart'; part 'player_overlay_parts.dart';
const double _topBarHeight = 58;
const double _topButtonSize = 36; const double _topButtonSize = 36;
const double _railButtonSize = 36; const double _topBarHeight = 58;
const double _railGap = 9; const double _railButtonSize = 34;
const double _fullScreenPillBottom = 246; const double _railGap = 18;
const double _panelRadius = 16; const double _panelRadius = 16;
/// K29 竖屏播放页浮层。 /// K29 竖屏播放页浮层。
@@ -57,7 +54,6 @@ class PlayerPlaybackOverlay extends StatelessWidget {
_bottom(context), _bottom(context),
_rail(context), _rail(context),
], ],
_fullScreenPill(),
if (!controlsVisible) if (!controlsVisible)
Positioned( Positioned(
top: AppDimens.spaceSm, top: AppDimens.spaceSm,
@@ -144,7 +140,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
final compact = MediaQuery.sizeOf(context).height < 700; final compact = MediaQuery.sizeOf(context).height < 700;
return Positioned( return Positioned(
right: AppDimens.spaceMd, right: AppDimens.spaceMd,
top: _topBarHeight + (compact ? 18 : 54), top: MediaQuery.sizeOf(context).height * (compact ? 0.42 : 0.55),
child: _Rail( child: _Rail(
l10n: data.l10n, l10n: data.l10n,
liked: data.liked, liked: data.liked,
@@ -156,7 +152,6 @@ class PlayerPlaybackOverlay extends StatelessWidget {
onComments: actions.onComments, onComments: actions.onComments,
onSave: actions.onSave, onSave: actions.onSave,
onShare: actions.onShare, onShare: actions.onShare,
compact: compact,
), ),
); );
} }
@@ -170,7 +165,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
bottom: 0, bottom: 0,
child: Container( child: Container(
key: const Key('player-controls-bottom'), key: const Key('player-controls-bottom'),
padding: const EdgeInsets.fromLTRB(14, 10, 14, 10), padding: const EdgeInsets.fromLTRB(14, 8, 14, 6),
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Color(0xED000000), color: Color(0xED000000),
borderRadius: BorderRadius.vertical( borderRadius: BorderRadius.vertical(
@@ -182,27 +177,16 @@ class PlayerPlaybackOverlay extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_detailRow(series), _detailRow(series),
const SizedBox(height: 6), const SizedBox(height: 4),
_EpisodeSynopsis( _EpisodeSynopsis(
key: const Key('player-episode-synopsis'), key: const Key('player-episode-synopsis'),
l10n: data.l10n, l10n: data.l10n,
episodeNumber: data.episode.number, episodeNumber: data.episode.number,
synopsis: synopsis, synopsis: synopsis,
authorNote: data.authorNote,
textScale: data.textScale, textScale: data.textScale,
), ),
if (data.authorNote.isNotEmpty) ...[ const SizedBox(height: 2),
const SizedBox(height: 6),
Text(
data.authorNote,
key: const Key('player-author-note'),
style: const TextStyle(color: Colors.white60, fontSize: 11),
),
],
const SizedBox(height: 6),
_PlayerTimeLabel(
key: const Key('player-time-label'),
controller: data.controller,
),
SeekProgressBar( SeekProgressBar(
key: const Key('player-progress'), key: const Key('player-progress'),
valueListenable: data.controller, valueListenable: data.controller,
@@ -226,7 +210,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
key: const Key('player-open-detail'), key: const Key('player-open-detail'),
onTap: actions.onDetail, onTap: actions.onDetail,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2), padding: const EdgeInsets.symmetric(vertical: 1),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
@@ -238,7 +222,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
style: TextStyle( style: TextStyle(
color: AppColors.onPrimary, color: AppColors.onPrimary,
fontFamily: 'Outfit', fontFamily: 'Outfit',
fontSize: 19 * data.textScale, fontSize: 18 * data.textScale,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
), ),
), ),
@@ -267,7 +251,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
onTap: actions.onEpisodes, onTap: actions.onEpisodes,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 4),
child: Row( child: Row(
children: [ children: [
Flexible( Flexible(
@@ -288,7 +272,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
const Icon( const Icon(
Icons.keyboard_arrow_up_rounded, Icons.keyboard_arrow_up_rounded,
color: AppColors.onPrimary, color: AppColors.onPrimary,
size: 18, size: 16,
), ),
], ],
), ),
@@ -298,57 +282,13 @@ class PlayerPlaybackOverlay extends StatelessWidget {
), ),
if (actions.onPip != null) ...[ if (actions.onPip != null) ...[
const SizedBox(width: 8), const SizedBox(width: 8),
_TopButton( _PipButton(
key: const Key('player-pip'), key: const Key('player-pip'),
tooltip: data.l10n.pictureInPicture, tooltip: data.l10n.pictureInPicture,
icon: Icons.picture_in_picture_alt_rounded,
onPressed: actions.onPip!, onPressed: actions.onPip!,
), ),
], ],
], ],
); );
} }
Widget _fullScreenPill() {
return Positioned(
left: 0,
right: 0,
bottom: _fullScreenPillBottom,
child: Center(
child: Material(
color: const Color(0x99000000),
borderRadius: BorderRadius.circular(999),
child: InkWell(
key: const Key('player-fullscreen-toggle'),
borderRadius: BorderRadius.circular(999),
onTap: controlsVisible ? actions.onClear : actions.onExitClear,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 7),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.fullscreen_rounded,
color: AppColors.onPrimary,
size: 16,
),
const SizedBox(width: 5),
Text(
controlsVisible
? data.l10n.fullScreenWatch
: data.l10n.exitClearScreen,
style: const TextStyle(
color: AppColors.onPrimary,
fontSize: 12,
fontWeight: FontWeight.w700,
),
),
],
),
),
),
),
),
);
}
} }
@@ -73,6 +73,30 @@ class _SpeedEntry extends StatelessWidget {
} }
} }
class _PipButton extends StatelessWidget {
const _PipButton({super.key, required this.tooltip, required this.onPressed});
final String tooltip;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: 30,
child: IconButton(
tooltip: tooltip,
padding: EdgeInsets.zero,
style: IconButton.styleFrom(
backgroundColor: const Color(0x80000000),
foregroundColor: AppColors.onPrimary,
),
onPressed: onPressed,
icon: const Icon(Icons.picture_in_picture_alt_rounded, size: 17),
),
);
}
}
class _Rail extends StatelessWidget { class _Rail extends StatelessWidget {
const _Rail({ const _Rail({
required this.l10n, required this.l10n,
@@ -85,7 +109,6 @@ class _Rail extends StatelessWidget {
required this.onComments, required this.onComments,
required this.onSave, required this.onSave,
required this.onShare, required this.onShare,
required this.compact,
}); });
final AppLocalizations l10n; final AppLocalizations l10n;
@@ -98,7 +121,6 @@ class _Rail extends StatelessWidget {
final VoidCallback onComments; final VoidCallback onComments;
final VoidCallback onSave; final VoidCallback onSave;
final VoidCallback onShare; final VoidCallback onShare;
final bool compact;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -111,29 +133,28 @@ class _Rail extends StatelessWidget {
label: favoriteCount?.toString() ?? l10n.favorite, label: favoriteCount?.toString() ?? l10n.favorite,
active: saved, active: saved,
onTap: onSave, onTap: onSave,
compact: compact,
), ),
const SizedBox(height: _railGap),
_RailButton( _RailButton(
key: const Key('player-rail-comments'), key: const Key('player-rail-comments'),
icon: Icons.chat_bubble_outline_rounded, icon: Icons.chat_bubble_outline_rounded,
label: commentCount?.toString() ?? l10n.comments, label: commentCount?.toString() ?? l10n.comments,
onTap: onComments, onTap: onComments,
compact: compact,
), ),
const SizedBox(height: _railGap),
_RailButton( _RailButton(
key: const Key('player-rail-like'), key: const Key('player-rail-like'),
icon: liked ? Icons.favorite_rounded : Icons.favorite_border_rounded, icon: liked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
label: likeCount?.toString() ?? l10n.like, label: likeCount?.toString() ?? l10n.like,
active: liked, active: liked,
onTap: onLike, onTap: onLike,
compact: compact,
), ),
const SizedBox(height: _railGap),
_RailButton( _RailButton(
key: const Key('player-rail-share'), key: const Key('player-rail-share'),
icon: Icons.ios_share_rounded, icon: Icons.ios_share_rounded,
label: l10n.share, label: l10n.share,
onTap: onShare, onTap: onShare,
compact: compact,
), ),
], ],
); );
@@ -146,21 +167,17 @@ class _RailButton extends StatelessWidget {
required this.icon, required this.icon,
required this.label, required this.label,
required this.onTap, required this.onTap,
required this.compact,
this.active = false, this.active = false,
}); });
final IconData icon; final IconData icon;
final String label; final String label;
final VoidCallback onTap; final VoidCallback onTap;
final bool compact;
final bool active; final bool active;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Column(
padding: EdgeInsets.only(bottom: compact ? 3 : _railGap),
child: Column(
children: [ children: [
SizedBox.square( SizedBox.square(
dimension: _railButtonSize, dimension: _railButtonSize,
@@ -171,21 +188,20 @@ class _RailButton extends StatelessWidget {
backgroundColor: const Color(0x80000000), backgroundColor: const Color(0x80000000),
foregroundColor: active ? AppColors.blue : AppColors.onPrimary, foregroundColor: active ? AppColors.blue : AppColors.onPrimary,
), ),
icon: Icon(icon, size: 18), icon: Icon(icon, size: 24),
), ),
), ),
SizedBox(height: compact ? 1 : 3),
Text( Text(
label, label,
maxLines: 1, maxLines: 1,
style: TextStyle( style: const TextStyle(
color: AppColors.onPrimary, color: AppColors.onPrimary,
fontSize: compact ? 8 : 9, fontSize: 11,
height: 1,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
], ],
),
); );
} }
} }
@@ -196,12 +212,14 @@ class _EpisodeSynopsis extends StatefulWidget {
required this.l10n, required this.l10n,
required this.episodeNumber, required this.episodeNumber,
required this.synopsis, required this.synopsis,
required this.authorNote,
required this.textScale, required this.textScale,
}); });
final AppLocalizations l10n; final AppLocalizations l10n;
final int episodeNumber; final int episodeNumber;
final String synopsis; final String synopsis;
final String authorNote;
final double textScale; final double textScale;
@override @override
@@ -213,8 +231,12 @@ class _EpisodeSynopsisState extends State<_EpisodeSynopsis> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final canExpand = widget.synopsis.trim().length > 28; return Material(
return Column( color: Colors.transparent,
child: InkWell(
key: const Key('player-synopsis-toggle'),
onTap: () => setState(() => _expanded = !_expanded),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
@@ -237,68 +259,36 @@ class _EpisodeSynopsisState extends State<_EpisodeSynopsis> {
child: Text( child: Text(
widget.synopsis, widget.synopsis,
key: const Key('player-synopsis'), key: const Key('player-synopsis'),
maxLines: _expanded ? 4 : 1, maxLines: _expanded ? 3 : 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: Colors.white70, color: Colors.white70,
fontSize: 11 * widget.textScale, fontSize: 11 * widget.textScale,
height: 1.45, height: 1.35,
), ),
), ),
), ),
], const SizedBox(width: 4),
), Icon(
if (canExpand) _expanded
GestureDetector( ? Icons.keyboard_arrow_up_rounded
key: const Key('player-synopsis-toggle'), : Icons.keyboard_arrow_down_rounded,
onTap: () => setState(() => _expanded = !_expanded),
child: Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
_expanded ? widget.l10n.showLess : widget.l10n.showMore,
style: const TextStyle(
color: Colors.white54, color: Colors.white54,
fontSize: 10, size: 16,
fontWeight: FontWeight.w600,
),
),
),
), ),
], ],
); ),
} if (_expanded && widget.authorNote.isNotEmpty) ...[
} const SizedBox(height: 4),
Text(
class _PlayerTimeLabel extends StatelessWidget { widget.authorNote,
const _PlayerTimeLabel({super.key, required this.controller}); key: const Key('player-author-note'),
style: const TextStyle(color: Colors.white54, fontSize: 10),
final VideoPlayerController? controller; ),
],
@override ],
Widget build(BuildContext context) {
final source = controller;
if (source == null) return _label(Duration.zero, Duration.zero);
return ValueListenableBuilder<VideoPlayerValue>(
valueListenable: source,
builder: (context, value, _) => _label(value.position, value.duration),
);
}
Widget _label(Duration position, Duration duration) => Align(
alignment: Alignment.centerRight,
child: Text(
'${_format(position)} / ${_format(duration)}',
style: const TextStyle(
color: Colors.white60,
fontSize: 9,
fontWeight: FontWeight.w600,
), ),
), ),
); );
String _format(Duration value) {
final minutes = value.inMinutes.remainder(60).toString().padLeft(2, '0');
final seconds = value.inSeconds.remainder(60).toString().padLeft(2, '0');
return '$minutes:$seconds';
} }
} }
+51 -18
View File
@@ -106,7 +106,7 @@ void main() {
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget); expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
expect(find.byType(PlayerCenterToggle), findsOneWidget); expect(find.byType(PlayerCenterToggle), findsOneWidget);
await tester.tap(find.byKey(const Key('player-fullscreen-toggle'))); await _clearFromMore(tester);
await tester.pump(); await tester.pump();
expect(find.byKey(const Key('player-controls-top')), findsNothing); expect(find.byKey(const Key('player-controls-top')), findsNothing);
@@ -173,13 +173,53 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}); });
testWidgets('should_keep_compact_bottom_panel_and_lower_rail', (
tester,
) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
final screenHeight = tester.view.physicalSize.height;
final bottom = tester.getRect(
find.byKey(const Key('player-controls-bottom')),
);
final rail = tester.getRect(
find.byKey(const Key('player-interaction-rail')),
);
expect(bottom.height, lessThanOrEqualTo(200));
expect(bottom.top, greaterThanOrEqualTo(screenHeight * 0.78));
expect(rail.top, greaterThanOrEqualTo(screenHeight * 0.55 - 2));
expect(rail.bottom, lessThanOrEqualTo(bottom.top));
expect(find.byKey(const Key('player-author-note')), findsNothing);
expect(
tester
.getSize(
find.descendant(
of: find.byKey(const Key('player-rail-comments')),
matching: find.byIcon(Icons.chat_bubble_outline_rounded),
),
)
.width,
24,
);
await tester.tap(find.byKey(const Key('player-synopsis-toggle')));
await tester.pumpAndSettle();
final expandedBottom = tester.getRect(
find.byKey(const Key('player-controls-bottom')),
);
expect(expandedBottom.height, lessThanOrEqualTo(200));
expect(expandedBottom.top, greaterThanOrEqualTo(screenHeight * 0.78));
});
testWidgets('should_keep_series_clear_state_when_swiping_next_episode', ( testWidgets('should_keep_series_clear_state_when_swiping_next_episode', (
tester, tester,
) async { ) async {
await _pumpApp(tester); await _pumpApp(tester);
await _openSeriesPlayer(tester); await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-fullscreen-toggle'))); await _clearFromMore(tester);
await tester.pump(); await tester.pump();
expect(find.byKey(const Key('player-controls-top')), findsNothing); expect(find.byKey(const Key('player-controls-top')), findsNothing);
@@ -237,7 +277,7 @@ void main() {
await tester.tap(find.byKey(const Key('player-speed-1.5'))); await tester.tap(find.byKey(const Key('player-speed-1.5')));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-fullscreen-toggle'))); await _clearFromMore(tester);
await tester.pump(); await tester.pump();
expect(find.byKey(const Key('player-more')), findsNothing); expect(find.byKey(const Key('player-more')), findsNothing);
@@ -383,19 +423,6 @@ void main() {
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget); expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
}); });
testWidgets('should_toggle_fullscreen_from_the_same_pill', (tester) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-fullscreen-toggle')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-controls-top')), findsNothing);
await tester.tap(find.byKey(const Key('player-fullscreen-toggle')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-controls-top')), findsOneWidget);
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
});
testWidgets('should_open_unlock_panel_with_honest_method_states', ( testWidgets('should_open_unlock_panel_with_honest_method_states', (
tester, tester,
) async { ) async {
@@ -434,7 +461,6 @@ void _expectFullscreenOverlay(WidgetTester tester) {
expect(find.byKey(const Key('player-drama-title')), findsOneWidget); expect(find.byKey(const Key('player-drama-title')), findsOneWidget);
expect(find.byKey(const Key('player-episode-label')), findsOneWidget); expect(find.byKey(const Key('player-episode-label')), findsOneWidget);
expect(find.byKey(const Key('player-synopsis')), findsOneWidget); expect(find.byKey(const Key('player-synopsis')), findsOneWidget);
expect(find.byKey(const Key('player-time-label')), findsOneWidget);
expect(find.byKey(const Key('player-more')), findsOneWidget); expect(find.byKey(const Key('player-more')), findsOneWidget);
for (final key in const [Key('player-back'), Key('player-more')]) { for (final key in const [Key('player-back'), Key('player-more')]) {
expect(tester.getSize(find.byKey(key)), const Size(36, 36)); expect(tester.getSize(find.byKey(key)), const Size(36, 36));
@@ -442,7 +468,7 @@ void _expectFullscreenOverlay(WidgetTester tester) {
expect(find.byKey(const Key('player-play-toggle')), findsNothing); expect(find.byKey(const Key('player-play-toggle')), findsNothing);
expect(find.byKey(const Key('player-episodes')), findsOneWidget); expect(find.byKey(const Key('player-episodes')), findsOneWidget);
expect(find.byKey(const Key('player-rail-comments')), findsOneWidget); expect(find.byKey(const Key('player-rail-comments')), findsOneWidget);
expect(find.byKey(const Key('player-fullscreen-toggle')), findsOneWidget); expect(find.byKey(const Key('player-fullscreen-toggle')), findsNothing);
expect(find.byType(Slider), findsOneWidget); expect(find.byType(Slider), findsOneWidget);
expect(find.byKey(const Key('player-title')), findsNothing); expect(find.byKey(const Key('player-title')), findsNothing);
expect(find.byKey(const Key('player-subtitle')), findsNothing); expect(find.byKey(const Key('player-subtitle')), findsNothing);
@@ -457,6 +483,13 @@ void _expectFullscreenOverlay(WidgetTester tester) {
expect(find.byKey(const Key('player-rail-share')), findsOneWidget); expect(find.byKey(const Key('player-rail-share')), findsOneWidget);
} }
Future<void> _clearFromMore(WidgetTester tester) async {
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-more-clear')));
await tester.pumpAndSettle();
}
Future<void> _openSeriesPlayer( Future<void> _openSeriesPlayer(
WidgetTester tester, { WidgetTester tester, {
Key cardKey = const Key('home-drama-card-city-lights-demo'), Key cardKey = const Key('home-drama-card-city-lights-demo'),