fix(player): 收敛播放页入口加载态

This commit is contained in:
Zhou Weidong committed 2026-10-26 17:56:40 +08:00
1 parent ee4e573f4f
commit b291044acc
7 files changed
+164 -90

No files matched your search

@@ -17,36 +17,26 @@ class PlayerLoadingOverlay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return IgnorePointer(
key: const Key('player-entry-loading-overlay'),
child: AnimatedOpacity(
opacity: opacity,
duration: const Duration(milliseconds: 140),
curve: Curves.easeOut,
onEnd: onFadeEnd,
child: ColoredBox(
color: AppColors.mediaBlack,
child: Center(
child: Container(
key: const Key('player-loading-surface'),
width: AppDimens.refreshIndicatorSize,
height: AppDimens.refreshIndicatorSize,
decoration: BoxDecoration(
color: AppColors.refreshIndicatorSurface,
borderRadius: BorderRadius.circular(
AppDimens.refreshIndicatorRadius,
),
),
alignment: Alignment.center,
child: const SizedBox.square(
dimension: AppDimens.refreshSpinnerSize,
child: CircularProgressIndicator(
key: Key('player-entry-loading'),
color: Colors.white,
strokeWidth: AppDimens.refreshSpinnerStroke,
),
),
),
return AnimatedOpacity(
opacity: opacity,
duration: const Duration(milliseconds: 140),
curve: Curves.easeOut,
onEnd: onFadeEnd,
child: Container(
key: const Key('player-loading-surface'),
width: AppDimens.refreshIndicatorSize,
height: AppDimens.refreshIndicatorSize,
decoration: BoxDecoration(
color: AppColors.refreshIndicatorSurface,
borderRadius: BorderRadius.circular(AppDimens.refreshIndicatorRadius),
),
alignment: Alignment.center,
child: const SizedBox.square(
dimension: AppDimens.refreshSpinnerSize,
child: CircularProgressIndicator(
key: Key('player-entry-loading'),
color: Colors.white,
strokeWidth: AppDimens.refreshSpinnerStroke,
),
),
),
@@ -304,6 +304,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
thumbnailsUrl: data.episode.thumbnailsUrl,
episodeId: data.episode.id,
inactiveTrackColor: AppColors.inactiveTrack,
fallbackDuration: Duration(seconds: data.episode.durationSec),
onScrubStart: actions.onScrubStart,
onScrubEnd: actions.onScrubEnd,
onSeek: actions.onSeek,
@@ -53,13 +53,11 @@ class PlayerRenderStack extends StatefulWidget {
required this.pageController,
required this.slots,
this.onCurrentVideoVisible,
this.showNeighbors = true,
});
final PageController pageController;
final Map<PlayerRenderSlotRole, PlayerRenderSlotData> slots;
final ValueChanged<int?>? onCurrentVideoVisible;
final bool showNeighbors;
@override
State<PlayerRenderStack> createState() => _PlayerRenderStackState();
@@ -117,13 +115,11 @@ class _PlayerRenderStackState extends State<PlayerRenderStack> {
: MediaQuery.sizeOf(context).height;
final pageOffset = _pageOffset();
final currentPage = _currentSlot.pagePosition ?? pageOffset;
final slots = widget.showNeighbors
? [
_slotData(PlayerRenderSlotRole.previous),
_slotData(PlayerRenderSlotRole.current),
_slotData(PlayerRenderSlotRole.next),
]
: [_slotData(PlayerRenderSlotRole.current)];
final slots = [
_slotData(PlayerRenderSlotRole.previous),
_slotData(PlayerRenderSlotRole.current),
_slotData(PlayerRenderSlotRole.next),
];
return Stack(
key: const Key('player-render-stack'),
fit: StackFit.expand,
@@ -42,6 +42,7 @@ class SeekProgressBar extends StatefulWidget {
this.spriteAxisService,
this.episodeId,
this.thumbnailsUrl,
this.fallbackDuration = Duration.zero,
});
final ValueListenable<VideoPlayerValue>? valueListenable;
@@ -57,6 +58,7 @@ class SeekProgressBar extends StatefulWidget {
final SpriteThumbnailAxisService? spriteAxisService;
final String? episodeId;
final String? thumbnailsUrl;
final Duration fallbackDuration;
@override
State<SeekProgressBar> createState() => _SeekProgressBarState();
@@ -220,7 +222,10 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
}
Widget _buildTrack(BuildContext context, VideoPlayerValue video) {
final total = video.duration.inMilliseconds;
final duration = video.duration > Duration.zero
? video.duration
: widget.fallbackDuration;
final total = duration.inMilliseconds;
final scrubbing = _dragging;
final loading = !widget.locked && !scrubbing && _buffering;
final enabled =
@@ -234,7 +239,7 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
final fraction = _previewFraction.value ?? played;
final previewPosition = _previewFraction.value == null
? video.position
: seekPositionForFraction(fraction, video.duration);
: seekPositionForFraction(fraction, duration);
final showPreview =
scrubbing &&
widget.showTimes &&
@@ -248,11 +253,26 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
final track = Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.showTimes && !video.isInitialized)
Padding(
padding: const EdgeInsets.only(bottom: 2),
child: Text(
'00:00 / ${_format(duration)}',
key: const Key('player-progress-uninitialized-time'),
textAlign: TextAlign.center,
style: const TextStyle(
color: AppColors.onPrimary,
fontSize: 12,
fontWeight: FontWeight.w600,
height: 1.2,
),
),
),
if (widget.showTimes && scrubbing && !showPreview)
Padding(
padding: const EdgeInsets.only(bottom: 2),
child: Text(
'${_format(previewPosition)} / ${_format(video.duration)}',
'${_format(previewPosition)} / ${_format(duration)}',
textAlign: TextAlign.center,
style: const TextStyle(
color: AppColors.onPrimary,
@@ -350,7 +370,7 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
thumbnailsUrl: widget.thumbnailsUrl,
episodeId: widget.episodeId!,
position: previewPosition,
duration: video.duration,
duration: duration,
),
),
],