fix(player): 修复竖滑上一集不自动播放

This commit is contained in:
Zhou Weidong committed 2026-10-26 13:43:43 +08:00
1 parent df36890b48
commit 516593499c
10 files changed
+264 -80

No files matched your search

+58 -20
View File
@@ -2,6 +2,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
@@ -124,6 +125,8 @@ class _PlayerPageState extends State<PlayerPage>
double? _speedBeforeBoost;
bool? _chromeBeforeBoost;
DateTime? _lastDoubleTapAt;
DateTime? _swipeStartedAt;
bool _swipePrewarmCaptured = false;
/// 收藏切换后的本地增量:基准是详情快照,切换成功按服务端状态 ±1。
final Map<String, int> _favoriteDelta = {};
@@ -308,6 +311,34 @@ class _PlayerPageState extends State<PlayerPage>
unawaited(logic.setPlaybackSpeed(speed));
}
bool _handlePageScroll(ScrollNotification notification) {
if (notification is ScrollStartNotification &&
notification.dragDetails != null) {
_swipeStartedAt = DateTime.now();
_swipePrewarmCaptured = false;
} else if (notification is ScrollUpdateNotification &&
!_swipePrewarmCaptured &&
notification.dragDetails != null) {
final delta = notification.scrollDelta ?? 0;
if (delta != 0) {
_swipePrewarmCaptured = true;
logic.session.prewarmNeighbors(forward: delta > 0);
}
} else if (notification is ScrollEndNotification) {
_swipePrewarmCaptured = false;
}
return false;
}
void _logSwipeReveal() {
if (!kDebugMode) return;
final startedAt = _swipeStartedAt;
if (startedAt == null) return;
_swipeStartedAt = null;
final elapsed = DateTime.now().difference(startedAt).inMilliseconds;
debugPrint('[player] swipe reveal ${elapsed}ms');
}
Future<void> _refreshHomeFeed() async {
final refresh = widget.onRefreshFeed;
if (refresh == null) return;
@@ -420,25 +451,28 @@ class _PlayerPageState extends State<PlayerPage>
final content = AnimatedBuilder(
animation: logic.session,
builder: (context, _) {
final pages = PageView.builder(
controller: logic.pages,
scrollDirection: Axis.vertical,
allowImplicitScrolling: true,
physics: widget.onRefreshFeed == null
? null
: const FeedRefreshPhysics(),
itemCount: indices.length,
onPageChanged: (position) {
final index = indices[position];
widget.onDramaChanged?.call(logic.queue.entryAt(index).drama);
unawaited(logic.selectEpisode(index));
if (position >= indices.length - 3) {
final loadMore = widget.onLoadMore;
if (loadMore != null) unawaited(loadMore());
}
},
itemBuilder: (context, position) =>
_buildEpisode(context, indices[position], interactions),
final pages = NotificationListener<ScrollNotification>(
onNotification: _handlePageScroll,
child: PageView.builder(
controller: logic.pages,
scrollDirection: Axis.vertical,
allowImplicitScrolling: true,
physics: widget.onRefreshFeed == null
? null
: const FeedRefreshPhysics(),
itemCount: indices.length,
onPageChanged: (position) {
final index = indices[position];
widget.onDramaChanged?.call(logic.queue.entryAt(index).drama);
unawaited(logic.selectEpisode(index));
if (position >= indices.length - 3) {
final loadMore = widget.onLoadMore;
if (loadMore != null) unawaited(loadMore());
}
},
itemBuilder: (context, position) =>
_buildEpisode(context, indices[position], interactions),
),
);
if (widget.onRefreshFeed == null) return pages;
return FeedPullRefresh(
@@ -550,6 +584,7 @@ class _PlayerPageState extends State<PlayerPage>
final handoffPort = handoff is VideoPlayerPort ? handoff : null;
// 测试播放器没有纹理。有播放器但不是视频控制器时视为已就绪,避免加载圈一直转。
final videoReady = videoPort?.controller.value.isInitialized ?? false;
if (selected && videoReady) _logSwipeReveal();
final ready = videoReady || port != null;
final theater = logic.pip || logic.pipPreparing;
final locked = logic.session.isLocked || episode.locked;
@@ -577,7 +612,10 @@ class _PlayerPageState extends State<PlayerPage>
handoff: handoffPort?.controller,
videoUrl: videoPort?.controller.dataSource ?? episode.videoUrl,
theater: theater,
openingFrame: playerOpeningFrame(episode.thumbnailsUrl),
openingFrame: playerOpeningFrame(
episode.thumbnailsUrl,
posterUrl: drama.posterUrl,
),
),
if (selected &&
!theater &&