feat(recommend): 新增分区流全部短剧与剧单

This commit is contained in:
Zhou Weidong committed 2026-10-22 17:23:22 +08:00
1 parent 0ef2438100
commit f1b5418954
22 files changed
+1426 -722

No files matched your search

+5 -131
View File
@@ -8,7 +8,6 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../../core/config/app_config.dart';
import '../../core/data/models/drama.dart';
import '../../core/data/services/home_feed_controller.dart';
import '../../core/data/services/catalog_controller.dart';
import '../../core/data/services/catalog_retry.dart';
@@ -27,13 +26,11 @@ import '../favorites/favorites_page.dart';
import '../filter/filter_page.dart';
import '../mine/mine_types.dart';
import '../new_releases/new_releases_page.dart';
import '../player/widgets/home_feed_header.dart';
import '../player/player_view.dart';
import '../ranking/ranking_page.dart';
import '../recommend/recommend_page.dart';
import '../mine/mine_view.dart';
import '../store/vip_page.dart';
import '../wallet/wallet_page.dart';
import 'home_feed_channel.dart';
import 'home_binding.dart';
import 'home_logic.dart';
import 'widgets/home_feed_grid.dart';
@@ -209,15 +206,11 @@ class _HomeTabs extends StatefulWidget {
class _HomeTabsState extends State<_HomeTabs> {
late final HomeLogic logic;
List<Drama>? _visibleDramas;
HomeFeedChannel? _visibleChannel;
@override
void initState() {
super.initState();
logic = HomeBinding().create(widget.feedController.dramas);
_visibleDramas = widget.feedController.dramas;
_visibleChannel = widget.feedController.channel;
widget.feedController.addListener(_onFeedChanged);
}
@@ -297,132 +290,13 @@ class _HomeTabsState extends State<_HomeTabs> {
}
Widget _recommend(BuildContext context) {
final currentDramas = widget.feedController.dramas;
final currentChannel = widget.feedController.channel;
if (currentDramas.isNotEmpty) {
_visibleDramas = currentDramas;
_visibleChannel = currentChannel;
}
if (currentDramas.isEmpty && !widget.feedController.loadingFirstPage) {
return _feedChannelPlaceholder(context);
}
final visibleDramas = _visibleDramas;
final visibleChannel = _visibleChannel;
final switching =
currentDramas.isEmpty && widget.feedController.loadingFirstPage;
if (visibleDramas == null ||
visibleDramas.isEmpty ||
visibleChannel == null) {
return _feedChannelPlaceholder(context);
}
final playerDramas = currentDramas.isEmpty ? visibleDramas : currentDramas;
final playerChannel = currentDramas.isEmpty
? visibleChannel
: currentChannel;
return Stack(
fit: StackFit.expand,
children: [
PlayerPage(
homeMode: true,
embedded: true,
active: logic.tab == 1,
drama: playerDramas.first,
initialIndex: 0,
feedDramas: playerDramas,
feedChannel: playerChannel,
headerChannel: currentChannel,
onOpenFullPlayer: (drama, episode) =>
logic.playDrama(context, drama, episodeId: episode.id),
onRefreshFeed: widget.feedController.refreshCurrent,
onLoadMore: widget.feedController.loadMore,
onChannelSelected: _selectFeedChannel,
onDramaChanged: logic.onDramaChanged,
onImmersiveChanged: logic.onImmersiveChanged,
onSearch: () => _openSearch(context),
onDiscover: () => logic.select(1),
onMy: () => logic.select(3),
),
if (switching)
Positioned.fill(
child: IgnorePointer(
key: const Key('home-feed-channel-loading'),
child: ColoredBox(
color: AppColors.controlSoftScrim,
child: Center(
child: SizedBox.square(
dimension: 24,
child: CircularProgressIndicator(
strokeWidth: 2.4,
color: AppColors.muted,
),
),
),
),
),
),
],
return RecommendPage(
feedController: widget.feedController,
onSearch: () => _openSearch(context),
onOpenFilter: () => _pushPage(context, const FilterPage()),
);
}
Widget _feedChannelPlaceholder(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Stack(
fit: StackFit.expand,
children: [
const ColoredBox(color: AppColors.mediaBlack),
SafeArea(
bottom: false,
child: Column(
children: [
HomeFeedHeader(
l10n: l10n,
channel: widget.feedController.channel,
onChannelSelected: _selectFeedChannel,
onRefresh: () => _refreshPlaceholder(context),
onSearch: () => _openSearch(context),
onMore: () {},
),
Expanded(
child: widget.feedController.loadingFirstPage
? const Center(
child: SizedBox.square(
dimension: 24,
child: CircularProgressIndicator(
key: Key('home-feed-channel-loading'),
strokeWidth: 2.4,
color: AppColors.muted,
),
),
)
: EmptyState(
icon: Icons.movie_outlined,
title: l10n.noStories,
actionLabel: l10n.retry,
onAction: () =>
unawaited(widget.feedController.refreshCurrent()),
),
),
],
),
),
],
);
}
Future<bool> _refreshPlaceholder(BuildContext context) async {
final ok = await widget.feedController.refreshCurrent();
if (!ok && context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(AppLocalizations.of(context)!.catalogError)),
);
}
return ok;
}
void _selectFeedChannel(HomeFeedChannel channel) {
unawaited(widget.feedController.selectChannel(channel));
}
void _openSearch(BuildContext context) {
Navigator.of(context).push<void>(
MaterialPageRoute(builder: (_) => const DiscoverPage(focusSearch: true)),