From b6666290ba9e128dbde4ee174b844eab5c1fc71e Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Thu, 22 Oct 2026 20:08:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(recommend):=20=E6=81=A2=E5=A4=8D=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=8B=96=E5=8A=A8=E5=89=8D=E6=B5=AE=E5=B1=82=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plans/PROGRESS.md | 2 +- lib/core/theme/app_colors.dart | 1 + lib/pages/player/player_view.dart | 15 +++------ .../player/widgets/home_feed_overlay.dart | 29 +++++------------ .../widgets/home_feed_overlay_parts.dart | 6 ++-- test/home/home_preview_layout_test.dart | 31 ++++++++++++++----- test/recommend/recommend_sections_test.dart | 6 ++++ 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/docs/plans/PROGRESS.md b/docs/plans/PROGRESS.md index 040637c..c2fc4c1 100644 --- a/docs/plans/PROGRESS.md +++ b/docs/plans/PROGRESS.md @@ -1184,5 +1184,5 @@ $ flutter test - 剧名 19/w600,箭头 20 白色并紧邻剧名;标签行改为 13/w600 亮灰内联布局。 - 简介「展开/收起」沿用现有三语文案;进度条热区恢复 24 并接入拖动自动清屏与预览卡片。 - 拖动期间隐藏操作栏、文字及根底栏,顶部导航常驻;松手后持续清屏直到点击画面。 -- 进度条固定中心并动画到 6 高,时间气泡限制在左右 12;按当前流程未执行 analyze/test。 +- 进度条固定中心并动画到 6 高,时间气泡限制在左右 12;松手恢复拖动前浮层状态。 - 修复 `scrubCancelRequest` 误置于 `initState` 的编译错误,并清理推荐页未使用变量;`flutter analyze` 无问题。 diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index 7d55946..c7aca6f 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -18,6 +18,7 @@ abstract final class AppColors { static const scrim = Color(0xD1000000); static const controlScrim = Color(0x80000000); static const controlSoftScrim = Color(0x42000000); + static const timeBubbleScrim = Color(0xB3000000); static const scrubPreviewScrim = Color(0xDE000000); static const overlaySoft = Color(0x66000000); static const overlayBar = Color(0x4D000000); diff --git a/lib/pages/player/player_view.dart b/lib/pages/player/player_view.dart index 2fbaa88..dc9d0d4 100644 --- a/lib/pages/player/player_view.dart +++ b/lib/pages/player/player_view.dart @@ -119,7 +119,6 @@ class _PlayerPageState extends State double _playbackSpeed = 1.0; bool _boosting = false; bool _scrubbing = false; - bool _clearScreenFromScrub = false; double? _speedBeforeBoost; bool? _chromeBeforeBoost; @@ -315,26 +314,24 @@ class _PlayerPageState extends State widget.onScrubVisibilityChanged?.call(value); } - void _finishFeedScrub() { + void _finishFeedScrub(bool wasVisible) { setState(() { _scrubbing = false; - _chromeVisible = false; - _clearScreenFromScrub = true; + _chromeVisible = wasVisible; }); + widget.onScrubVisibilityChanged?.call(!wasVisible); } void _cancelFeedScrub() { logic.cancelScrub(); _scrubbing = false; _chromeVisible = true; - _clearScreenFromScrub = false; } void _restoreFeedChrome() { setState(() { _scrubbing = false; _chromeVisible = true; - _clearScreenFromScrub = false; }); widget.onScrubVisibilityChanged?.call(false); } @@ -749,11 +746,7 @@ class _PlayerPageState extends State ? null : () => _openUnlockSheet(context, index, episode), ), - if (widget.homeMode && - !_chromeVisible && - !_boosting && - !_scrubbing && - !_clearScreenFromScrub) + if (widget.homeMode && !_chromeVisible && !_boosting && !_scrubbing) Positioned( right: 12, bottom: 56, diff --git a/lib/pages/player/widgets/home_feed_overlay.dart b/lib/pages/player/widgets/home_feed_overlay.dart index 13891d0..f254f84 100644 --- a/lib/pages/player/widgets/home_feed_overlay.dart +++ b/lib/pages/player/widgets/home_feed_overlay.dart @@ -89,7 +89,7 @@ class HomeFeedOverlay extends StatefulWidget { final VoidCallback onBoostEnd; final VoidCallback onMore; final VoidCallback? onScrubStart; - final VoidCallback? onScrubEnd; + final ValueChanged? onScrubEnd; final ValueChanged? onScrubVisibilityChanged; final ValueChanged? onSeek; final int cancelScrubRequest; @@ -102,14 +102,13 @@ class HomeFeedOverlay extends StatefulWidget { class _HomeFeedOverlayState extends State { bool _scrubbing = false; - bool _clearAfterScrub = false; + bool _wasVisibleBeforeScrub = true; @override void didUpdateWidget(covariant HomeFeedOverlay oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.cancelScrubRequest != widget.cancelScrubRequest) { _scrubbing = false; - _clearAfterScrub = false; } } @@ -138,7 +137,7 @@ class _HomeFeedOverlayState extends State { ), if (widget.boosting) Positioned(left: 0, right: 0, bottom: 20, child: _boostHint()) - else if (widget.visible && !_scrubbing && !_clearAfterScrub) + else if (widget.visible && !_scrubbing) Positioned( left: _pageHorizontal, right: _railRight, @@ -176,31 +175,19 @@ class _HomeFeedOverlayState extends State { } void _startScrub() { - if (!_scrubbing || _clearAfterScrub) { - setState(() { - _scrubbing = true; - _clearAfterScrub = false; - }); - } + _wasVisibleBeforeScrub = widget.visible; + if (!_scrubbing) setState(() => _scrubbing = true); widget.onScrubVisibilityChanged?.call(true); widget.onScrubStart?.call(); } void _endScrub() { - if (_scrubbing || !_clearAfterScrub) { - setState(() { - _scrubbing = false; - _clearAfterScrub = true; - }); - } - widget.onScrubEnd?.call(); + final wasVisible = _wasVisibleBeforeScrub; + if (_scrubbing) setState(() => _scrubbing = false); + widget.onScrubEnd?.call(wasVisible); } void _handleSurfaceTap() { - if (_clearAfterScrub) { - setState(() => _clearAfterScrub = false); - widget.onScrubVisibilityChanged?.call(false); - } widget.onTogglePlay(); } diff --git a/lib/pages/player/widgets/home_feed_overlay_parts.dart b/lib/pages/player/widgets/home_feed_overlay_parts.dart index 2e054ac..034fbab 100644 --- a/lib/pages/player/widgets/home_feed_overlay_parts.dart +++ b/lib/pages/player/widgets/home_feed_overlay_parts.dart @@ -150,7 +150,7 @@ class _FeedProgressBarState extends State<_FeedProgressBar> { if (showPreview) Positioned( left: _timeBubbleLeft(width, _preview!), - bottom: widget.hitHeight + 8, + bottom: _lineCenterFromBottom + 16, child: _ScrubTimeBubble( key: const Key('scrub-preview-time-bubble'), position: previewPosition, @@ -377,9 +377,9 @@ class _ScrubTimeBubble extends StatelessWidget { Widget build(BuildContext context) { return Container( width: _timeBubbleWidth, - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3), decoration: BoxDecoration( - color: AppColors.overlayMedium, + color: AppColors.timeBubbleScrim, borderRadius: BorderRadius.circular(6), ), child: Text( diff --git a/test/home/home_preview_layout_test.dart b/test/home/home_preview_layout_test.dart index cfd815d..bdb5012 100644 --- a/test/home/home_preview_layout_test.dart +++ b/test/home/home_preview_layout_test.dart @@ -719,6 +719,28 @@ void main() { tester.getRect(find.byKey(const Key('home-feed-gesture'))).right - 12, ), ); + expect( + tester + .getRect(find.byKey(const Key('home-feed-progress-track'))) + .center + .dy - + bubbleRect.bottom, + closeTo(16, 0.1), + ); + final bubbleContainer = tester.widget( + find.descendant( + of: find.byKey(const Key('scrub-preview-time-bubble')), + matching: find.byType(Container), + ), + ); + expect( + (bubbleContainer.decoration! as BoxDecoration).color, + AppColors.timeBubbleScrim, + ); + expect( + bubbleContainer.padding, + const EdgeInsets.symmetric(horizontal: 6, vertical: 3), + ); await gesture.moveBy(const Offset(-600, 0)); await tester.pump(); expect( @@ -765,8 +787,8 @@ void main() { ); await gesture.up(); await tester.pumpAndSettle(); - expect(scrubVisibility.last, isTrue); - expect(find.byKey(const Key('home-feed-title')), findsNothing); + expect(scrubVisibility.last, isFalse); + expect(find.byKey(const Key('home-feed-title')), findsOneWidget); expect(seeked, isNotNull); expect(seeked!.inSeconds, greaterThan(0)); expect( @@ -778,11 +800,6 @@ void main() { 2, ); - await tester.tap(find.byKey(const Key('home-feed-gesture'))); - await tester.pump(); - expect(scrubVisibility.last, isFalse); - expect(find.byKey(const Key('home-feed-title')), findsOneWidget); - await tester.tap(find.byKey(const Key('home-feed-full-series'))); await tester.pump(); expect(opened, 1); diff --git a/test/recommend/recommend_sections_test.dart b/test/recommend/recommend_sections_test.dart index 1cbfb35..7646fbe 100644 --- a/test/recommend/recommend_sections_test.dart +++ b/test/recommend/recommend_sections_test.dart @@ -102,9 +102,15 @@ void main() { await tester.pump(const Duration(milliseconds: 130)); expect(find.byKey(const Key('recommend-top-nav')), findsOneWidget); expect(tester.getCenter(progress).dy, closeTo(progressCenterY, 0.1)); + final navVisibility = find.ancestor( + of: find.byKey(const Key('home-tabs-bar')), + matching: find.byType(Visibility), + ); + expect(tester.widget(navVisibility.first).visible, isFalse); await scrub.up(); await tester.pumpAndSettle(); expect(find.byKey(const Key('recommend-top-nav')), findsOneWidget); + expect(tester.widget(navVisibility.first).visible, isTrue); await tester.tap(find.byKey(const Key('recommend-tab-playlist'))); await tester.pumpAndSettle();