fix(flutter): feed 清屏保留顶栏并寻址恢复播放

This commit is contained in:
Zhou Weidong committed 2026-10-20 14:33:35 +08:00
1 parent 9b99d96a07
commit c87798fb16
5 files changed
+83 -28

No files matched your search

+11 -1
View File
@@ -578,7 +578,11 @@ class PlayerLogic extends ChangeNotifier {
await session.playbackSettled;
if (scrubbingPlayer != player || session.active != player) return;
await player.controller.seekTo(position);
if (session.active == player) await saveCurrentProgress();
if (session.active == player) {
// 暂停时拖动进度后直接恢复播放,避免画面停在旧位置。
resumeAfterSeek();
await saveCurrentProgress();
}
} catch (_) {
if (context.mounted && session.active == player) {
final l10n = AppLocalizations.of(context)!;
@@ -591,6 +595,12 @@ class PlayerLogic extends ChangeNotifier {
}
}
/// 拖动进度落点后恢复播放;暂停态拖动不应停留在暂停。
@visibleForTesting
void resumeAfterSeek() {
if (!session.userWantsPlay) session.setUserWantsPlay(true);
}
Future<void> leave(BuildContext context) async {
await saveCurrentProgress();
if (context.mounted) Navigator.of(context).pop();
+6 -11
View File
@@ -510,17 +510,12 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
),
if (widget.homeMode && !_chromeVisible)
Positioned(
top: 0,
right: 0,
child: SafeArea(
left: false,
bottom: false,
minimum: const EdgeInsets.only(top: 8, right: 12),
child: ExitClearScreenButton(
key: const Key('home-feed-exit-clear-screen'),
tooltip: l10n.exitClearScreen,
onPressed: () => setState(() => _chromeVisible = true),
),
right: 12,
bottom: 56,
child: ExitClearScreenButton(
key: const Key('home-feed-exit-clear-screen'),
tooltip: l10n.exitClearScreen,
onPressed: () => setState(() => _chromeVisible = true),
),
),
if (widget.homeMode &&
@@ -131,23 +131,17 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
),
if (widget.boosting)
Column(children: [const Spacer(), _boostHint(), _fullSeriesBar()])
else if (widget.visible)
else
Column(
children: [
_header(context),
Expanded(
child: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 10, 12),
child: _rail(),
),
),
),
_bottomInfo(),
const Spacer(),
if (widget.visible) _bottomInfo(),
_fullSeriesBar(),
],
),
if (widget.visible && !widget.boosting)
Positioned(right: 10, bottom: 56, child: _rail()),
],
),
);
@@ -307,7 +301,7 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
Widget _bottomInfo() {
return Padding(
padding: const EdgeInsets.fromLTRB(14, 0, 14, 8),
padding: const EdgeInsets.fromLTRB(14, 0, 56, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
+39 -4
View File
@@ -114,13 +114,48 @@ void main() {
final railBottom = tester
.getRect(find.byKey(const Key('rail-share')))
.bottom;
final infoTop = tester
.getRect(find.byKey(const Key('home-feed-series-meta')))
final seriesTop = tester
.getRect(find.byKey(const Key('home-feed-full-series')))
.top;
final titleRight = tester
.getRect(find.byKey(const Key('home-feed-title')))
.right;
final railLeft = tester.getRect(find.byKey(const Key('rail-save'))).left;
expect(railTop, greaterThan(844 * 0.45));
expect(railBottom, lessThanOrEqualTo(infoTop));
expect(infoTop - railBottom, lessThanOrEqualTo(20));
expect(seriesTop - railBottom, closeTo(12, 1));
expect(titleRight, lessThanOrEqualTo(railLeft + 2));
});
testWidgets('should_keep_feed_header_and_progress_after_clear', (
tester,
) async {
await _pumpApp(tester);
final gesture = await tester.startGesture(const Offset(195, 300));
await tester.pump(const Duration(milliseconds: 700));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-more-clear')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-feed-refresh')), findsOneWidget);
expect(find.byKey(const Key('home-feed-tab-recommend')), findsOneWidget);
expect(find.byKey(const Key('home-feed-search')), findsOneWidget);
expect(find.byKey(const Key('home-feed-full-series')), findsOneWidget);
expect(find.byKey(const Key('home-feed-progress')), findsOneWidget);
expect(find.byKey(const Key('rail-save')), findsNothing);
expect(find.byKey(const Key('home-feed-title')), findsNothing);
final exit = tester.getRect(
find.byKey(const Key('home-feed-exit-clear-screen')),
);
expect(exit.right, greaterThan(340));
expect(exit.center.dy, greaterThan(600));
await tester.tap(find.byKey(const Key('home-feed-exit-clear-screen')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('rail-save')), findsOneWidget);
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
});
testWidgets('should_boost_feed_on_side_long_press', (tester) async {
+21
View File
@@ -215,6 +215,27 @@ void main() {
logic.dispose();
await _drain(logic);
});
test('should_resume_playback_after_seek_when_paused', () async {
final logic = _logic(FakeWatchHistory());
logic.attach(
PlayerPage(drama: _drama('signal'), initialIndex: 0),
isMounted: () => true,
);
logic.start(
factory: _RecordingFactory().create,
coordinator: PlaybackCoordinator(),
);
await _drain(logic);
logic.session.setUserWantsPlay(false);
expect(logic.session.userWantsPlay, isFalse);
logic.resumeAfterSeek();
expect(logic.session.userWantsPlay, isTrue);
logic.dispose();
await _drain(logic);
});
});
group('history writes', () {