feat(player): 保持屏幕常亮并自动恢复播放
This commit is contained in:
1 parent
5bf10221a8
commit
a25c500371
7 files changed
+273
-1
No files matched your search
@@ -92,6 +92,7 @@ class PlaybackSession extends ChangeNotifier {
|
||||
}
|
||||
return slot.player;
|
||||
}
|
||||
|
||||
bool get loading => _loading;
|
||||
bool get userWantsPlay => _userWantsPlay;
|
||||
bool get canAutoAdvance => _mayPlay && !_loading && active != null;
|
||||
@@ -103,6 +104,10 @@ class PlaybackSession extends ChangeNotifier {
|
||||
Future<void> get playbackSettled => _operations;
|
||||
Future<void> get preloadSettled => _preloadTask;
|
||||
|
||||
/// 当前页面可见、无浮层遮挡且存在可用播放器时可安全恢复。
|
||||
bool get canResumeAfterBackground =>
|
||||
!_closed && _routeVisible && !_overlayOpen && active != null;
|
||||
|
||||
bool get _visible => !_closed && _appResumed && _routeVisible;
|
||||
bool get _mayPlay => _visible && !_overlayOpen && _userWantsPlay;
|
||||
|
||||
|
||||
@@ -512,6 +512,7 @@ class PlayerLogic extends ChangeNotifier {
|
||||
void onLifecycle(AppLifecycleState state) {
|
||||
if (state != AppLifecycleState.resumed) unawaited(saveCurrentProgress());
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
final wasInPip = pip || pipPreparing;
|
||||
// 部分机型退出画中画不会回调 onPipChanged(false):回前台先兜底复位,
|
||||
// 否则 chromeHidden 恒为 true,播放浮层与首页底栏都会消失。
|
||||
if (pip || pipPreparing) {
|
||||
@@ -523,8 +524,17 @@ class PlayerLogic extends ChangeNotifier {
|
||||
// 签名地址有有效期:回前台时若票据已过期,重新取一张再起播,
|
||||
// 否则会撞上 403(契约 §1.4)
|
||||
final episode = trackedEpisode;
|
||||
final shouldAutoResume = !wasInPip && _canAutoResume(episode);
|
||||
if (episode != null && !playback.isFresh(episode.id)) {
|
||||
unawaited(selectEpisode(session.currentIndex));
|
||||
unawaited(
|
||||
_refreshTicketThenResume(
|
||||
episode,
|
||||
session.currentIndex,
|
||||
shouldAutoResume,
|
||||
),
|
||||
);
|
||||
} else if (shouldAutoResume) {
|
||||
session.setUserWantsPlay(true);
|
||||
}
|
||||
}
|
||||
session.setAppResumed(
|
||||
@@ -533,6 +543,31 @@ class PlayerLogic extends ChangeNotifier {
|
||||
if (state != AppLifecycleState.resumed) cancelScrub();
|
||||
}
|
||||
|
||||
Future<void> _refreshTicketThenResume(
|
||||
Episode episode,
|
||||
int index,
|
||||
bool shouldResume,
|
||||
) async {
|
||||
await selectEpisode(index);
|
||||
if (!shouldResume ||
|
||||
!isMounted() ||
|
||||
trackedEpisode?.id != episode.id ||
|
||||
!_canAutoResume(episode)) {
|
||||
return;
|
||||
}
|
||||
session.setUserWantsPlay(true);
|
||||
}
|
||||
|
||||
bool _canAutoResume(Episode? episode) {
|
||||
return episode != null &&
|
||||
ticketError == null &&
|
||||
blockedEpisodeId != episode.id &&
|
||||
unlockingEpisodeId == null &&
|
||||
!session.isLocked &&
|
||||
session.error == null &&
|
||||
session.canResumeAfterBackground;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_disposed) return;
|
||||
|
||||
Reference in new issue
Block a user