fix(recommend): 精简底部信息并优化进度拖动
This commit is contained in:
1 parent
ccda41b15b
commit
d66ac8327e
16 files changed
+141
-163
No files matched your search
@@ -19,7 +19,7 @@ import 'seek_progress_bar.dart';
|
||||
part 'home_feed_overlay_parts.dart';
|
||||
|
||||
const double _progressHeight = 2;
|
||||
const double _progressHitHeight = 12;
|
||||
const double _progressHitHeight = 24;
|
||||
const double _pageHorizontal = 14;
|
||||
const double _railRight = 8;
|
||||
const double _railGap = 12;
|
||||
@@ -54,10 +54,11 @@ class HomeFeedOverlay extends StatefulWidget {
|
||||
required this.onMore,
|
||||
this.likeCount,
|
||||
this.favoriteCount,
|
||||
this.rankingRank,
|
||||
this.commentCount,
|
||||
this.authorNote = '',
|
||||
this.onScrubStart,
|
||||
this.onScrubEnd,
|
||||
this.onScrubVisibilityChanged,
|
||||
this.onSeek,
|
||||
this.thumbnailService,
|
||||
this.spriteAxisService,
|
||||
@@ -71,7 +72,6 @@ class HomeFeedOverlay extends StatefulWidget {
|
||||
final bool liked;
|
||||
final int? likeCount;
|
||||
final int? favoriteCount;
|
||||
final int? rankingRank;
|
||||
final int? commentCount;
|
||||
final bool saved;
|
||||
final String authorNote;
|
||||
@@ -89,6 +89,8 @@ class HomeFeedOverlay extends StatefulWidget {
|
||||
final VoidCallback onBoostEnd;
|
||||
final VoidCallback onMore;
|
||||
final VoidCallback? onScrubStart;
|
||||
final VoidCallback? onScrubEnd;
|
||||
final ValueChanged<bool>? onScrubVisibilityChanged;
|
||||
final ValueChanged<Duration>? onSeek;
|
||||
final PlaybackThumbnailService? thumbnailService;
|
||||
final SpriteThumbnailAxisService? spriteAxisService;
|
||||
@@ -98,6 +100,8 @@ class HomeFeedOverlay extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
||||
bool _scrubbing = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
@@ -123,7 +127,7 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
||||
),
|
||||
if (widget.boosting)
|
||||
Positioned(left: 0, right: 0, bottom: 20, child: _boostHint())
|
||||
else if (widget.visible)
|
||||
else if (widget.visible && !_scrubbing)
|
||||
Positioned(
|
||||
left: _pageHorizontal,
|
||||
right: _railRight,
|
||||
@@ -149,7 +153,8 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
||||
locked: widget.locked,
|
||||
height: _progressHeight,
|
||||
hitHeight: _progressHitHeight,
|
||||
onScrubStart: widget.onScrubStart,
|
||||
onScrubStart: _startScrub,
|
||||
onScrubEnd: _endScrub,
|
||||
onSeek: widget.onSeek,
|
||||
thumbnailService: widget.thumbnailService,
|
||||
spriteAxisService: widget.spriteAxisService,
|
||||
@@ -163,6 +168,18 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
||||
);
|
||||
}
|
||||
|
||||
void _startScrub() {
|
||||
if (!_scrubbing) setState(() => _scrubbing = true);
|
||||
widget.onScrubVisibilityChanged?.call(true);
|
||||
widget.onScrubStart?.call();
|
||||
}
|
||||
|
||||
void _endScrub() {
|
||||
if (_scrubbing) setState(() => _scrubbing = false);
|
||||
widget.onScrubVisibilityChanged?.call(false);
|
||||
widget.onScrubEnd?.call();
|
||||
}
|
||||
|
||||
void _handleLongPressStart(LongPressStartDetails details, double width) {
|
||||
final third = width / 3;
|
||||
final dx = details.localPosition.dx;
|
||||
@@ -220,7 +237,6 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
||||
episode: widget.episode,
|
||||
onDetail: widget.onDetail,
|
||||
onOpenFullPlayer: widget.onOpenFullPlayer,
|
||||
rankingRank: widget.rankingRank,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ class _FeedProgressBar extends StatefulWidget {
|
||||
required this.height,
|
||||
required this.hitHeight,
|
||||
this.onScrubStart,
|
||||
this.onScrubEnd,
|
||||
this.onSeek,
|
||||
this.thumbnailService,
|
||||
this.spriteAxisService,
|
||||
@@ -29,6 +30,7 @@ class _FeedProgressBar extends StatefulWidget {
|
||||
final double height;
|
||||
final double hitHeight;
|
||||
final VoidCallback? onScrubStart;
|
||||
final VoidCallback? onScrubEnd;
|
||||
final ValueChanged<Duration>? onSeek;
|
||||
final PlaybackThumbnailService? thumbnailService;
|
||||
final SpriteThumbnailAxisService? spriteAxisService;
|
||||
@@ -137,8 +139,18 @@ class _FeedProgressBarState extends State<_FeedProgressBar> {
|
||||
onHorizontalDragUpdate: interactive
|
||||
? (details) => _update(details.localPosition.dx / width)
|
||||
: null,
|
||||
onHorizontalDragEnd: interactive ? (_) => _commit(_preview) : null,
|
||||
onHorizontalDragCancel: interactive ? _cancelPreview : null,
|
||||
onHorizontalDragEnd: interactive
|
||||
? (_) {
|
||||
widget.onScrubEnd?.call();
|
||||
_commit(_preview);
|
||||
}
|
||||
: null,
|
||||
onHorizontalDragCancel: interactive
|
||||
? () {
|
||||
widget.onScrubEnd?.call();
|
||||
_cancelPreview();
|
||||
}
|
||||
: null,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
|
||||
@@ -10,9 +10,8 @@ import '../../../l10n/app_localizations.dart';
|
||||
import '../../home/widgets/home_drama_classification.dart';
|
||||
|
||||
const double _headlineFont = 26;
|
||||
const double _seriesFont = 17;
|
||||
const double _metaFont = 12;
|
||||
const double _tagFont = 12;
|
||||
const double _seriesFont = 19;
|
||||
const double _tagFont = 13;
|
||||
const double _synopsisFont = 13;
|
||||
const double _watchAllHeight = 44;
|
||||
const double _actionGap = 28;
|
||||
@@ -30,14 +29,12 @@ class HomeFeedInfoPanel extends StatefulWidget {
|
||||
required this.episode,
|
||||
required this.onDetail,
|
||||
required this.onOpenFullPlayer,
|
||||
this.rankingRank,
|
||||
});
|
||||
|
||||
final Drama drama;
|
||||
final Episode episode;
|
||||
final VoidCallback onDetail;
|
||||
final VoidCallback onOpenFullPlayer;
|
||||
final int? rankingRank;
|
||||
|
||||
@override
|
||||
State<HomeFeedInfoPanel> createState() => _HomeFeedInfoPanelState();
|
||||
@@ -73,15 +70,14 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_metaPills(l10n),
|
||||
if (_hasMeta()) const SizedBox(height: 8),
|
||||
GestureDetector(
|
||||
key: const Key('home-feed-series-name'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: widget.onDetail,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
Flexible(
|
||||
child: Text(
|
||||
dramaTitle,
|
||||
maxLines: 1,
|
||||
@@ -94,10 +90,11 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
const Icon(
|
||||
Icons.chevron_right_rounded,
|
||||
size: 16,
|
||||
color: AppColors.overlaySecondary,
|
||||
size: 20,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -114,81 +111,6 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
);
|
||||
}
|
||||
|
||||
bool _hasMeta() {
|
||||
return isHotDrama(widget.drama) || widget.drama.viewCount > 0;
|
||||
}
|
||||
|
||||
Widget _metaPills(AppLocalizations l10n) {
|
||||
final hot = isHotDrama(widget.drama);
|
||||
final views = widget.drama.viewCount;
|
||||
final rank = widget.rankingRank;
|
||||
if (!hot && views <= 0) return const SizedBox.shrink();
|
||||
return Wrap(
|
||||
key: const Key('home-feed-meta-pills'),
|
||||
spacing: 6,
|
||||
runSpacing: 4,
|
||||
children: [
|
||||
if (hot)
|
||||
_pill(
|
||||
key: const Key('home-feed-ranking-pill'),
|
||||
background: AppColors.error,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.local_fire_department_rounded,
|
||||
size: 12,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
rank != null && rank > 0
|
||||
? l10n.hotChartRanked(rank)
|
||||
: l10n.hotChartLabel,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: _metaFont,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (views > 0)
|
||||
_pill(
|
||||
key: const Key('home-feed-view-pill'),
|
||||
background: AppColors.overlaySoft,
|
||||
child: Text(
|
||||
formatPlayCount(views),
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: _metaFont,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _pill({
|
||||
required Key key,
|
||||
required Color background,
|
||||
required Widget child,
|
||||
}) {
|
||||
return Container(
|
||||
key: key,
|
||||
height: 22,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: background,
|
||||
borderRadius: BorderRadius.circular(11),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _tagMetaRow(AppLocalizations l10n, List<String> genres) {
|
||||
return Row(
|
||||
key: const Key('home-feed-tags'),
|
||||
@@ -210,20 +132,21 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
Expanded(
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: Text(
|
||||
genres.join(' '),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.overlaySecondary,
|
||||
color: AppColors.overlayLabel,
|
||||
fontSize: _tagFont,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
l10n.favoriteEpisodeProgress(
|
||||
widget.episode.number,
|
||||
@@ -233,8 +156,8 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
style: const TextStyle(
|
||||
color: AppColors.overlaySecondary,
|
||||
fontSize: _metaFont,
|
||||
color: AppColors.overlayLabel,
|
||||
fontSize: _tagFont,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -298,7 +221,7 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
bottom: 0,
|
||||
child: _synopsisToggle(
|
||||
key: const Key('home-feed-synopsis-more'),
|
||||
label: l10n.more,
|
||||
label: l10n.expandSynopsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user