feat(player): 重做播放页信息层级与互动栏点击动效

This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-30 22:53:18 +08:00
1 parent aed9ee2b01
commit fd2ba0bf43
15 files changed
+2074 -551

No files matched your search

+50 -39
View File
@@ -1271,6 +1271,22 @@ void main() {
expect(find.byKey(const Key('player-interaction-rail')), findsOneWidget);
});
testWidgets('should_keep_episode_entry_regular_when_player_is_open', (
tester,
) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
final entry = tester.widget<Text>(
find.descendant(
of: find.byKey(const Key('player-episodes-pill')),
matching: find.byType(Text),
),
);
expect(entry.style?.fontWeight, FontWeight.w400);
expect(entry.style?.fontSize, 13.5);
expect(entry.data, contains(' · '));
});
testWidgets('should_push_episodes_arrow_to_pill_right', (tester) async {
// 宽屏下文案不会撑满胶囊,才能验证箭头是否被推到最右侧。
await _pumpApp(tester, size: const Size(900, 844));
@@ -1371,9 +1387,9 @@ void main() {
final shareRect = tester.getRect(
find.byKey(const Key('player-rail-share')),
);
expect(likeRect.top - saveRect.bottom, closeTo(12, 0.1));
expect(commentsRect.top - likeRect.bottom, closeTo(12, 0.1));
expect(shareRect.top - commentsRect.bottom, closeTo(12, 0.1));
expect(likeRect.top - saveRect.bottom, closeTo(6, 0.1));
expect(commentsRect.top - likeRect.bottom, closeTo(6, 0.1));
expect(shareRect.top - commentsRect.bottom, closeTo(6, 0.1));
final saveButton = tester.widget<IconButton>(
find.descendant(
@@ -1405,7 +1421,9 @@ void main() {
);
});
testWidgets('should_toggle_synopsis_with_inline_text_button', (tester) async {
testWidgets('should_toggle_synopsis_at_fixed_corner_with_feed_motion', (
tester,
) async {
final longCopy = Drama(
id: 'long-copy-demo',
title: 'Long Title',
@@ -1428,7 +1446,7 @@ void main() {
await _pumpApp(tester, catalog: FakeCatalogRepository(dramas: [longCopy]));
await _openSeriesPlayer(tester, feedIndex: 0);
final toggle = find.byKey(const Key('player-synopsis-toggle'));
final toggle = find.byKey(const Key('player-synopsis-more'));
final synopsis = find.byKey(const Key('player-synopsis'));
expect(
find.descendant(of: toggle, matching: find.text('More')),
@@ -1443,17 +1461,15 @@ void main() {
?.color,
AppColors.textPrimary,
);
expect(tester.widget<Text>(synopsis).maxLines, 1);
expect(tester.widget<Text>(synopsis).maxLines, 2);
expect(tester.widget<Text>(synopsis).overflow, TextOverflow.ellipsis);
// 行尾「展开」与正文同一行,只留 6 的左边距。
expect(
tester
.widget<Padding>(
find.descendant(of: toggle, matching: find.byType(Padding)),
)
.padding,
const EdgeInsets.only(left: 6),
final motion = tester.widget<AnimatedSize>(
find.byKey(const Key('player-synopsis-size')),
);
expect(motion.duration, const Duration(milliseconds: 240));
expect(motion.curve, Curves.easeInOutCubic);
final blockFinder = find.byKey(const Key('player-episode-synopsis'));
final collapsedHeight = tester.getSize(blockFinder).height;
final synopsisRect = tester.getRect(synopsis);
final toggleRect = tester.getRect(toggle);
expect(toggleRect.left, greaterThan(synopsisRect.left));
@@ -1463,24 +1479,24 @@ void main() {
);
await tester.tap(toggle);
await tester.pump();
await tester.pump(const Duration(milliseconds: 80));
final growingHeight = tester.getSize(blockFinder).height;
expect(growingHeight, greaterThan(collapsedHeight));
expect(tester.getRect(toggle), toggleRect);
await tester.pumpAndSettle();
expect(
find.descendant(of: toggle, matching: find.text('Less')),
findsOneWidget,
);
expect(
tester.widget<Text>(find.byKey(const Key('player-synopsis'))).maxLines,
tester
.widget<Text>(find.byKey(const Key('player-synopsis-expanded')))
.maxLines,
isNull,
);
final lessRect = tester.getRect(toggle);
final textRect = tester.getRect(find.byKey(const Key('player-synopsis')));
final block = tester.getRect(
find.byKey(const Key('player-episode-synopsis')),
);
// 展开后「收起」内联在正文最后一行的行尾。
expect(lessRect.top, greaterThanOrEqualTo(textRect.top));
expect(lessRect.bottom, lessThanOrEqualTo(textRect.bottom + 1));
expect(lessRect.right - block.right, lessThanOrEqualTo(2));
expect(tester.getRect(toggle), toggleRect);
expect(tester.getSize(blockFinder).height, greaterThan(growingHeight));
await tester.tap(toggle);
await tester.pumpAndSettle();
@@ -1488,29 +1504,24 @@ void main() {
find.descendant(of: toggle, matching: find.text('More')),
findsOneWidget,
);
expect(tester.widget<Text>(synopsis).maxLines, 1);
expect(tester.widget<Text>(synopsis).maxLines, 2);
});
testWidgets('should_share_one_text_style_across_label_and_synopsis', (
testWidgets('should_match_feed_synopsis_without_episode_prefix', (
tester,
) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
// 新 UI 把「第 n 集」与简介合并进同一个富文本,整行共用一套白字规格。
final line = tester.widget<Text>(find.byKey(const Key('player-synopsis')));
final style = line.style ?? const TextStyle();
expect(style.fontSize, 12);
expect(style.fontWeight, FontWeight.w500);
expect(style.color, AppColors.onPrimary);
final span = line.textSpan! as TextSpan;
final separator = span.children!.whereType<TextSpan>().firstWhere(
(child) => (child.text ?? '').contains('|'),
);
expect(separator.style?.fontSize, 12);
expect(separator.style?.fontWeight, FontWeight.w400);
expect(separator.style?.color, AppColors.onPrimary.withValues(alpha: 0.45));
expect(style.fontSize, 15);
expect(style.fontWeight, FontWeight.w400);
expect(style.color, AppColors.overlaySecondary);
expect(style.shadows ?? <Shadow>[], isEmpty);
expect(line.textSpan!.toPlainText(), isNot(startsWith('Episode ')));
expect(line.textSpan!.toPlainText(), isNot(contains(' | ')));
expect(find.byKey(const Key('player-episode-heading')), findsOneWidget);
});
testWidgets('should_fit_long_title_and_synopsis_at_320_width', (
@@ -1563,7 +1574,7 @@ void main() {
tester.getRect(find.byKey(const Key('player-synopsis'))).right,
lessThanOrEqualTo(320 - 14 - 54),
);
expect(synopsis.maxLines, 1);
expect(synopsis.maxLines, 2);
expect(synopsis.overflow, TextOverflow.ellipsis);
expect(
tester.getRect(find.byKey(const Key('player-episodes-pill'))).right,