fix(player): 使用雪碧图预热首帧兜底
This commit is contained in:
1 parent
48b4e67d34
commit
70d8e0f982
13 files changed
+207
-322
No files matched your search
@@ -146,7 +146,9 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
_thumbnailService = PlaybackThumbnailService(
|
||||
sourceResolver: _resolveThumbnailSource,
|
||||
);
|
||||
_spriteAxisService = SpriteThumbnailAxisService();
|
||||
_spriteAxisService = SpriteThumbnailAxisService(
|
||||
spriteCacheCapacity: 8,
|
||||
)..addListener(_handleSpriteFrameChanged);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
logic.start(
|
||||
factory: context.read<PlayerFactory>(),
|
||||
@@ -266,7 +268,9 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
appRouteObserver.unsubscribe(this);
|
||||
_spriteAxisService.dispose();
|
||||
_spriteAxisService
|
||||
..removeListener(_handleSpriteFrameChanged)
|
||||
..dispose();
|
||||
_thumbnailService.dispose();
|
||||
logic.dispose();
|
||||
super.dispose();
|
||||
@@ -369,6 +373,30 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
_chromeVisible = true;
|
||||
}
|
||||
|
||||
void _handleSpriteFrameChanged() {
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
void _prewarmAdjacentThumbnails() {
|
||||
final current = logic.session.currentIndex;
|
||||
final indices = <int?>[
|
||||
current,
|
||||
logic.previousVisibleIndex(current),
|
||||
logic.nextVisibleIndex(current),
|
||||
];
|
||||
for (final index in indices) {
|
||||
if (index == null || index < 0 || index >= logic.sessionEpisodes.length) {
|
||||
continue;
|
||||
}
|
||||
final thumbnailsUrl = logic.sessionEpisodes[index].thumbnailsUrl;
|
||||
if (thumbnailsUrl != null) {
|
||||
unawaited(
|
||||
_spriteAxisService.prepareAt(thumbnailsUrl, Duration.zero),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _restoreFeedChrome() {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
@@ -451,6 +479,7 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
final content = AnimatedBuilder(
|
||||
animation: logic.session,
|
||||
builder: (context, _) {
|
||||
_prewarmAdjacentThumbnails();
|
||||
final pages = NotificationListener<ScrollNotification>(
|
||||
onNotification: _handlePageScroll,
|
||||
child: PageView.builder(
|
||||
@@ -590,6 +619,15 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
final videoFit = theater ? BoxFit.contain : BoxFit.cover;
|
||||
final preparedFrameAvailable =
|
||||
selected && 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),
|
||||
);
|
||||
}
|
||||
final locked = logic.session.isLocked || episode.locked;
|
||||
if (selected &&
|
||||
videoPort != null &&
|
||||
@@ -617,9 +655,10 @@ class _PlayerPageState extends State<PlayerPage>
|
||||
theater: theater,
|
||||
holdOpeningUntilFirstFrame: logic.session.userWantsPlay,
|
||||
preparedFrameAvailable: preparedFrameAvailable,
|
||||
openingFrameReady: openingFrameReady,
|
||||
openingFrame: playerOpeningFrame(
|
||||
episode.thumbnailsUrl,
|
||||
posterUrl: drama.posterUrl,
|
||||
thumbnailsUrl,
|
||||
spriteSource: _spriteAxisService,
|
||||
fit: videoFit,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user