feat(player): 进度条拖动预览改用雪碧图

This commit is contained in:
Zhou Weidong committed 2026-10-22 11:40:23 +08:00
1 parent 89a94f85c2
commit 12b733d111
16 files changed
+1312 -31

No files matched your search

+19 -2
View File
@@ -14,6 +14,7 @@ import '../../core/data/services/download_controller.dart';
import '../../core/data/services/interaction_controller.dart';
import '../../core/data/services/playback_position_cache.dart';
import '../../core/data/services/playback_session.dart';
import '../../core/data/services/sprite_thumbnail_axis.dart';
import '../../core/data/services/playback_thumbnail_service.dart';
import '../../core/data/services/video_player_port.dart';
import '../../core/data/services/wallet_controller.dart';
@@ -106,6 +107,7 @@ class _PlayerPageState extends State<PlayerPage>
with WidgetsBindingObserver, RouteAware {
late final PlayerLogic logic;
late final PlaybackThumbnailService _thumbnailService;
late final SpriteThumbnailAxisService _spriteAxisService;
PageRoute<dynamic>? _subscribedRoute;
bool _chromeVisible = true;
double _playbackSpeed = 1.0;
@@ -131,6 +133,7 @@ class _PlayerPageState extends State<PlayerPage>
_thumbnailService = PlaybackThumbnailService(
sourceResolver: _resolveThumbnailSource,
);
_spriteAxisService = SpriteThumbnailAxisService();
WidgetsBinding.instance.addObserver(this);
logic.start(
factory: context.read<PlayerFactory>(),
@@ -247,6 +250,7 @@ class _PlayerPageState extends State<PlayerPage>
void dispose() {
WidgetsBinding.instance.removeObserver(this);
appRouteObserver.unsubscribe(this);
_spriteAxisService.dispose();
_thumbnailService.dispose();
logic.dispose();
super.dispose();
@@ -422,9 +426,12 @@ class _PlayerPageState extends State<PlayerPage>
final l10n = AppLocalizations.of(context)!;
final entry = logic.queue.entryAt(index);
final drama = entry.drama;
final episode = widget.homeMode
? logic.displayEpisode(drama, entry.episode)
final sessionEpisode = index >= 0 && index < logic.sessionEpisodes.length
? logic.sessionEpisodes[index]
: entry.episode;
final episode = widget.homeMode
? logic.displayEpisode(drama, sessionEpisode)
: sessionEpisode;
final selected = index == logic.session.currentIndex;
// Selection changes before the prepared slot is promoted. Use its controller
// throughout the handoff instead of briefly falling back to a placeholder.
@@ -435,6 +442,14 @@ class _PlayerPageState extends State<PlayerPage>
final ready = videoPort?.controller.value.isInitialized ?? false;
final theater = logic.pip || logic.pipPreparing;
final locked = logic.session.isLocked || episode.locked;
if (selected && ready) {
unawaited(
_spriteAxisService.prepareAt(
episode.thumbnailsUrl,
videoPort!.controller.value.position,
),
);
}
return Stack(
fit: StackFit.expand,
@@ -606,6 +621,7 @@ class _PlayerPageState extends State<PlayerPage>
? (position) => logic.seekTo(context, videoPort!, position)
: null,
thumbnailService: _thumbnailService,
spriteAxisService: _spriteAxisService,
)
else
PlayerPlaybackOverlay(
@@ -629,6 +645,7 @@ class _PlayerPageState extends State<PlayerPage>
totalEpisodes: logic.visibleIndices.length,
boosting: _boosting,
thumbnailService: _thumbnailService,
spriteAxisService: _spriteAxisService,
),
actions: PlayerOverlayActions(
onBack: widget.embedded