feat(app): 完善播放协议搜索与空状态

This commit is contained in:
Zhou Weidong committed 2026-10-23 12:38:47 +08:00
1 parent 671e0ce143
commit ef29fc5f15
85 files changed
+2976 -768

No files matched your search

+36 -27
View File
@@ -25,12 +25,18 @@ class RecommendPage extends StatefulWidget {
required this.feedController,
required this.active,
required this.onSearch,
this.videoOnly = false,
this.onImmersiveChanged,
});
final HomeFeedController feedController;
final bool active;
final VoidCallback onSearch;
/// 画中画时只留视频,不画顶栏。
final bool videoOnly;
final ValueChanged<bool>? onImmersiveChanged;
@override
State<RecommendPage> createState() => _RecommendPageState();
}
@@ -84,40 +90,42 @@ class _RecommendPageState extends State<RecommendPage> {
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: IgnorePointer(
child: SizedBox(
height: 72,
child: DecoratedBox(
key: const Key('recommend-top-gradient'),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.mediaBlack, AppColors.transparent],
if (!widget.videoOnly)
Positioned(
top: 0,
left: 0,
right: 0,
child: IgnorePointer(
child: SizedBox(
height: 72,
child: DecoratedBox(
key: const Key('recommend-top-gradient'),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.mediaBlack, AppColors.transparent],
),
),
),
),
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: SafeArea(
bottom: false,
child: RecommendTopNav(
selected: _tab,
onVideo: _tab == RecommendInnerTab.feed,
onSelected: _selectTab,
onSearch: _handleSearch,
if (!widget.videoOnly)
Positioned(
top: 0,
left: 0,
right: 0,
child: SafeArea(
bottom: false,
child: RecommendTopNav(
selected: _tab,
onVideo: _tab == RecommendInnerTab.feed,
onSelected: _selectTab,
onSearch: _handleSearch,
),
),
),
),
],
),
);
@@ -155,6 +163,7 @@ class _RecommendPageState extends State<RecommendPage> {
_openDrama(drama, episodeId: episode.id),
onRefreshFeed: widget.feedController.refreshCurrent,
onLoadMore: widget.feedController.loadMore,
onImmersiveChanged: widget.onImmersiveChanged,
scrubCancelRequest: _scrubCancelRequest,
);
}
@@ -75,13 +75,7 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
child: EmptyState(
key: const Key('all-dramas-empty'),
icon: Icons.movie_filter_outlined,
title: l10n.homeGridFilterEmpty,
actionLabel: l10n.homeGridClearFilter,
onAction: () => setState(() {
_region = 'all';
_audio = 'all';
_genre = null;
}),
title: l10n.emptyContent,
),
)
else
@@ -12,6 +12,7 @@ const double _tabGap = 22;
const double _tabFont = 17;
const double _searchHitSize = 40;
const double _searchIconSize = 26;
const double _minNavWidth = 280;
class RecommendTopNav extends StatelessWidget {
const RecommendTopNav({
@@ -40,6 +41,22 @@ class RecommendTopNav extends StatelessWidget {
final shadows = onVideo
? const [Shadow(color: AppColors.mediaBlack, blurRadius: 6)]
: null;
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < _minNavWidth) {
return const SizedBox(key: Key('recommend-top-nav'), height: height);
}
return _bar(context, items, shadows);
},
);
}
Widget _bar(
BuildContext context,
List<(RecommendInnerTab, String, String)> items,
List<Shadow>? shadows,
) {
final l10n = AppLocalizations.of(context)!;
return SizedBox(
key: const Key('recommend-top-nav'),
height: height,
@@ -50,20 +67,23 @@ class RecommendTopNav extends StatelessWidget {
child: Stack(
alignment: Alignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
for (var index = 0; index < items.length; index++) ...[
if (index > 0) const SizedBox(width: _tabGap),
_tab(
key: Key('recommend-tab-${items[index].$3}'),
label: items[index].$2,
selected: selected == items[index].$1,
shadows: shadows,
onTap: () => onSelected(items[index].$1),
),
FittedBox(
fit: BoxFit.scaleDown,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
for (var index = 0; index < items.length; index++) ...[
if (index > 0) const SizedBox(width: _tabGap),
_tab(
key: Key('recommend-tab-${items[index].$3}'),
label: items[index].$2,
selected: selected == items[index].$1,
shadows: shadows,
onTap: () => onSelected(items[index].$1),
),
],
],
],
),
),
Align(
alignment: Alignment.centerRight,