From 4b1aea29c724dfc2dd7978e439ea3a4d7c244283 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Wed, 21 Oct 2026 10:52:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(player):=20=E5=8F=B3=E4=BE=A7=E4=BA=92?= =?UTF-8?q?=E5=8A=A8=E6=A0=8F=E5=9B=BE=E6=A0=87=E6=8C=89=E5=8F=82=E8=80=83?= =?UTF-8?q?=E5=9B=BE=E6=9B=BF=E6=8D=A2=E5=B9=B6=E6=94=BE=E5=A4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../player/widgets/home_feed_overlay.dart | 9 +-- .../player/widgets/interaction_rail.dart | 27 +++---- lib/pages/player/widgets/player_overlay.dart | 11 +-- test/home/home_preview_layout_test.dart | 33 +++++++++ test/player/player_fullscreen_test.dart | 72 ++++++++++++++++++- 5 files changed, 128 insertions(+), 24 deletions(-) diff --git a/lib/pages/player/widgets/home_feed_overlay.dart b/lib/pages/player/widgets/home_feed_overlay.dart index fb71a6b..41a1a84 100644 --- a/lib/pages/player/widgets/home_feed_overlay.dart +++ b/lib/pages/player/widgets/home_feed_overlay.dart @@ -173,7 +173,7 @@ class _HomeFeedOverlayState extends State { items: [ InteractionRailItem( key: const Key('rail-save'), - icon: Icons.star_border_rounded, + icon: Icons.star_rounded, activeIcon: Icons.star_rounded, label: widget.l10n.favorite, count: widget.favoriteCount, @@ -192,7 +192,7 @@ class _HomeFeedOverlayState extends State { ), InteractionRailItem( key: const Key('rail-like'), - icon: Icons.favorite_border_rounded, + icon: Icons.favorite_rounded, activeIcon: Icons.favorite_rounded, label: widget.l10n.like, count: widget.likeCount, @@ -202,9 +202,10 @@ class _HomeFeedOverlayState extends State { ), InteractionRailItem( key: const Key('rail-share'), - icon: Icons.ios_share_rounded, - activeIcon: Icons.ios_share_rounded, + icon: Icons.reply_rounded, + activeIcon: Icons.reply_rounded, label: widget.l10n.share, + mirrorIcon: true, onTap: widget.onShare, ), ], diff --git a/lib/pages/player/widgets/interaction_rail.dart b/lib/pages/player/widgets/interaction_rail.dart index 1411bc3..dcd19e5 100644 --- a/lib/pages/player/widgets/interaction_rail.dart +++ b/lib/pages/player/widgets/interaction_rail.dart @@ -5,10 +5,9 @@ import 'package:flutter/material.dart'; import '../../../core/formatting/count_format.dart'; import '../../../core/theme/app_colors.dart'; -const double _buttonSize = 34; -const double _iconSize = 24; -const double _itemGap = 18; -const Color _buttonBackground = Color(0x80000000); +const double _buttonSize = 44; +const double _iconSize = 30; +const double _itemGap = 22; /// 互动栏单项:图标、计数与点击。 class InteractionRailItem { @@ -21,6 +20,7 @@ class InteractionRailItem { this.count, this.countKey, this.selected = false, + this.mirrorIcon = false, }); final Key key; @@ -31,6 +31,7 @@ class InteractionRailItem { final int? count; final Key? countKey; final bool selected; + final bool mirrorIcon; } /// 播放页与首页 feed 共用的右侧互动栏:收藏/评论/喜欢/分享。 @@ -60,6 +61,10 @@ class _RailButton extends StatelessWidget { @override Widget build(BuildContext context) { + final icon = Icon( + item.selected ? item.activeIcon : item.icon, + size: _iconSize, + ); return Column( key: item.key, mainAxisSize: MainAxisSize.min, @@ -69,14 +74,10 @@ class _RailButton extends StatelessWidget { child: IconButton( onPressed: item.onTap, padding: EdgeInsets.zero, - style: IconButton.styleFrom( - backgroundColor: _buttonBackground, - foregroundColor: item.selected ? AppColors.blue : Colors.white, - ), - icon: Icon( - item.selected ? item.activeIcon : item.icon, - size: _iconSize, - ), + color: item.selected ? AppColors.blue : Colors.white, + icon: item.mirrorIcon + ? Transform.flip(flipX: true, child: icon) + : icon, ), ), const SizedBox(height: 2), @@ -88,7 +89,7 @@ class _RailButton extends StatelessWidget { style: const TextStyle( color: Colors.white, height: 1, - fontSize: 11, + fontSize: 12, fontWeight: FontWeight.w600, shadows: [Shadow(blurRadius: 6, color: Colors.black)], ), diff --git a/lib/pages/player/widgets/player_overlay.dart b/lib/pages/player/widgets/player_overlay.dart index 910cc13..f89e7ea 100644 --- a/lib/pages/player/widgets/player_overlay.dart +++ b/lib/pages/player/widgets/player_overlay.dart @@ -141,13 +141,13 @@ class PlayerPlaybackOverlay extends StatelessWidget { final compact = MediaQuery.sizeOf(context).height < 700; return Positioned( right: AppDimens.spaceMd, - top: MediaQuery.sizeOf(context).height * (compact ? 0.42 : 0.55), + top: MediaQuery.sizeOf(context).height * (compact ? 0.30 : 0.43), child: InteractionRail( key: const Key('player-interaction-rail'), items: [ InteractionRailItem( key: const Key('player-rail-save'), - icon: Icons.star_border_rounded, + icon: Icons.star_rounded, activeIcon: Icons.star_rounded, label: data.l10n.favorite, count: data.favoriteCount, @@ -166,7 +166,7 @@ class PlayerPlaybackOverlay extends StatelessWidget { ), InteractionRailItem( key: const Key('player-rail-like'), - icon: Icons.favorite_border_rounded, + icon: Icons.favorite_rounded, activeIcon: Icons.favorite_rounded, label: data.l10n.like, count: data.likeCount, @@ -176,9 +176,10 @@ class PlayerPlaybackOverlay extends StatelessWidget { ), InteractionRailItem( key: const Key('player-rail-share'), - icon: Icons.ios_share_rounded, - activeIcon: Icons.ios_share_rounded, + icon: Icons.reply_rounded, + activeIcon: Icons.reply_rounded, label: data.l10n.share, + mirrorIcon: true, onTap: actions.onShare, ), ], diff --git a/test/home/home_preview_layout_test.dart b/test/home/home_preview_layout_test.dart index 5059184..f01ab09 100644 --- a/test/home/home_preview_layout_test.dart +++ b/test/home/home_preview_layout_test.dart @@ -150,6 +150,39 @@ void main() { tester.widget(find.byKey(const Key('rail-comments-count'))).data, '12', ); + expect( + find.descendant( + of: find.byKey(const Key('rail-save')), + matching: find.byIcon(Icons.star_rounded), + ), + findsOneWidget, + ); + expect( + find.descendant( + of: find.byKey(const Key('rail-like')), + matching: find.byIcon(Icons.favorite_rounded), + ), + findsOneWidget, + ); + expect( + find.descendant( + of: find.byKey(const Key('rail-share')), + matching: find.byIcon(Icons.reply_rounded), + ), + findsOneWidget, + ); + expect( + tester + .widget( + find.descendant( + of: find.byKey(const Key('rail-share')), + matching: find.byType(Transform), + ), + ) + .transform + .storage[0], + -1, + ); expect(find.byKey(const Key('progress-loading')), findsOneWidget); expect(find.byKey(const Key('home-feed-progress-thumb')), findsNothing); }); diff --git a/test/player/player_fullscreen_test.dart b/test/player/player_fullscreen_test.dart index 518738e..14b6b1b 100644 --- a/test/player/player_fullscreen_test.dart +++ b/test/player/player_fullscreen_test.dart @@ -466,7 +466,7 @@ void main() { expect(bottom.height, lessThanOrEqualTo(200)); expect(bottom.top, greaterThanOrEqualTo(screenHeight * 0.78)); - expect(rail.top, greaterThanOrEqualTo(screenHeight * 0.55 - 2)); + expect(rail.top, greaterThanOrEqualTo(screenHeight * 0.40)); expect(rail.bottom, lessThanOrEqualTo(bottom.top)); expect(find.byKey(const Key('player-author-note')), findsNothing); expect( @@ -478,7 +478,7 @@ void main() { ), ) .width, - 24, + 30, ); await tester.tap(find.byKey(const Key('player-synopsis-toggle'))); @@ -580,6 +580,74 @@ void main() { expect(railLabel(const Key('player-rail-save')), '3201'); }); + testWidgets('should_render_reference_rail_icons_without_background', ( + tester, + ) async { + await _pumpApp(tester); + await _openSeriesPlayer(tester); + + Finder railIcon(Key key, IconData icon) => + find.descendant(of: find.byKey(key), matching: find.byIcon(icon)); + expect( + railIcon(const Key('player-rail-save'), Icons.star_rounded), + findsOneWidget, + ); + expect( + railIcon(const Key('player-rail-like'), Icons.favorite_rounded), + findsOneWidget, + ); + expect( + railIcon( + const Key('player-rail-comments'), + Icons.chat_bubble_outline_rounded, + ), + findsOneWidget, + ); + final shareIcon = railIcon( + const Key('player-rail-share'), + Icons.reply_rounded, + ); + expect(shareIcon, findsOneWidget); + expect(tester.widget(shareIcon).size, 30); + + final mirror = tester.widget( + find.descendant( + of: find.byKey(const Key('player-rail-share')), + matching: find.byType(Transform), + ), + ); + expect(mirror.transform.storage[0], -1); + + final saveButton = tester.widget( + find.descendant( + of: find.byKey(const Key('player-rail-save')), + matching: find.byType(IconButton), + ), + ); + expect(saveButton.style?.backgroundColor, isNull); + expect( + tester.getSize( + find.descendant( + of: find.byKey(const Key('player-rail-save')), + matching: find.byType(IconButton), + ), + ), + const Size(44, 44), + ); + expect( + tester + .widget( + find.descendant( + of: find.byKey(const Key('player-rail-like')), + matching: find.byType(Text), + ), + ) + .style + ?.fontSize, + 12, + ); + }); + testWidgets('should_toggle_synopsis_with_inline_text_button', (tester) async { await _pumpApp(tester); await _openSeriesPlayer(tester);