fix(player): 重构单层过渡并阻止锁定集串播
This commit is contained in:
1 parent
70d8e0f982
commit
0cb0ab0613
8 files changed
+657
-335
No files matched your search
@@ -146,9 +146,8 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
_thumbnailService = PlaybackThumbnailService(
|
||||
sourceResolver: _resolveThumbnailSource,
|
||||
);
|
||||
_spriteAxisService = SpriteThumbnailAxisService(
|
||||
spriteCacheCapacity: 8,
|
||||
)..addListener(_handleSpriteFrameChanged);
|
||||
_spriteAxisService = SpriteThumbnailAxisService(spriteCacheCapacity: 8)
|
||||
..addListener(_handleSpriteFrameChanged);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
logic.start(
|
||||
factory: context.read<PlayerFactory>(),
|
||||
@@ -389,10 +388,9 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
continue;
|
||||
}
|
||||
final thumbnailsUrl = logic.sessionEpisodes[index].thumbnailsUrl;
|
||||
if (thumbnailsUrl != null) {
|
||||
unawaited(
|
||||
_spriteAxisService.prepareAt(thumbnailsUrl, Duration.zero),
|
||||
);
|
||||
if (thumbnailsUrl != null &&
|
||||
!logic.isEpisodeLocked(logic.sessionEpisodes[index])) {
|
||||
unawaited(_spriteAxisService.prepareAt(thumbnailsUrl, Duration.zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,33 +601,36 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
)
|
||||
: displayed;
|
||||
final selected = index == logic.session.currentIndex;
|
||||
final locked =
|
||||
logic.isEpisodeLocked(episode) ||
|
||||
logic.session.isLocked ||
|
||||
logic.blockedEpisodeId == episode.id;
|
||||
// Selection changes before the prepared slot is promoted. Use its controller
|
||||
// throughout the handoff instead of briefly falling back to a placeholder.
|
||||
final port =
|
||||
(selected ? logic.session.active : null) ??
|
||||
logic.session.preparedPlayerAt(index);
|
||||
final port = locked
|
||||
? null
|
||||
: (selected ? logic.session.active : null) ??
|
||||
logic.session.preparedPlayerAt(index);
|
||||
final videoPort = port is VideoPlayerPort ? port : null;
|
||||
final handoff = selected ? logic.session.handoffAt(index) : null;
|
||||
final handoff = selected && !locked ? logic.session.handoffAt(index) : null;
|
||||
final handoffPort = handoff is VideoPlayerPort ? handoff : null;
|
||||
// 测试播放器没有纹理。有播放器但不是视频控制器时视为已就绪,避免加载圈一直转。
|
||||
final videoReady = videoPort?.controller.value.isInitialized ?? false;
|
||||
if (selected && videoReady) _logSwipeReveal();
|
||||
final ready = videoReady || port != null;
|
||||
final ready = !locked && (videoReady || port != null);
|
||||
final theater = logic.pip || logic.pipPreparing;
|
||||
final videoFit = theater ? BoxFit.contain : BoxFit.cover;
|
||||
final preparedFrameAvailable =
|
||||
selected && logic.session.reusedWarmAt(index);
|
||||
selected && !locked && logic.session.reusedWarmAt(index);
|
||||
final thumbnailsUrl = episode.thumbnailsUrl;
|
||||
final openingFrameReady =
|
||||
thumbnailsUrl != null &&
|
||||
_spriteAxisService.cachedFrameAt(thumbnailsUrl, Duration.zero) != null;
|
||||
if (thumbnailsUrl != null) {
|
||||
unawaited(
|
||||
_spriteAxisService.prepareAt(thumbnailsUrl, Duration.zero),
|
||||
);
|
||||
unawaited(_spriteAxisService.prepareAt(thumbnailsUrl, Duration.zero));
|
||||
}
|
||||
final locked = logic.session.isLocked || episode.locked;
|
||||
if (selected &&
|
||||
!locked &&
|
||||
videoPort != null &&
|
||||
videoPort.controller.value.isInitialized) {
|
||||
unawaited(
|
||||
@@ -649,20 +650,27 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
color: AppColors.mediaBlack,
|
||||
),
|
||||
PlayerVideoSurface(
|
||||
controller: videoPort?.controller,
|
||||
handoff: handoffPort?.controller,
|
||||
controller: locked ? null : videoPort?.controller,
|
||||
videoUrl: videoPort?.controller.dataSource ?? episode.videoUrl,
|
||||
theater: theater,
|
||||
holdOpeningUntilFirstFrame: logic.session.userWantsPlay,
|
||||
preparedFrameAvailable: preparedFrameAvailable,
|
||||
openingFrameReady: openingFrameReady,
|
||||
openingFrame: playerOpeningFrame(
|
||||
thumbnailsUrl,
|
||||
spriteSource: _spriteAxisService,
|
||||
fit: videoFit,
|
||||
),
|
||||
warmFrameAvailable: preparedFrameAvailable,
|
||||
thumbnailReady: openingFrameReady,
|
||||
waitForPlaybackFrame: logic.session.userWantsPlay,
|
||||
placeholder: locked
|
||||
? null
|
||||
: handoffPort != null
|
||||
? ControllerFramePlaceholder(
|
||||
controller: handoffPort.controller,
|
||||
theater: theater,
|
||||
)
|
||||
: playerOpeningFrame(
|
||||
thumbnailsUrl,
|
||||
spriteSource: _spriteAxisService,
|
||||
fit: videoFit,
|
||||
),
|
||||
),
|
||||
if (selected &&
|
||||
!locked &&
|
||||
!theater &&
|
||||
!ready &&
|
||||
!logic.ticketLoading &&
|
||||
@@ -884,10 +892,7 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
controlsVisible: _chromeVisible,
|
||||
),
|
||||
// 票据三态之三:后端判定不可播放 —— 用 accessType 驱动文案,不在前端猜
|
||||
if (selected &&
|
||||
!theater &&
|
||||
!ready &&
|
||||
logic.blockedEpisodeId == episode.id)
|
||||
if (selected && !theater && locked)
|
||||
PlayerBlockedNotice(
|
||||
l10n: l10n,
|
||||
episode: episode,
|
||||
|
||||
Reference in new issue
Block a user