feat(app): 客户端展示多语言并支持筛选分页

This commit is contained in:
Zhou Weidong committed 2026-10-24 17:20:24 +08:00
1 parent 8481611372
commit 8b50b5bd06
68 files changed
+2742 -1120

No files matched your search

+80
View File
@@ -6,8 +6,11 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../core/data/models/drama.dart';
import '../../core/data/remote/catalog_api.dart';
import '../../core/data/models/playlist_detail.dart';
import '../../core/data/services/category_controller.dart';
import '../../core/data/services/home_feed_controller.dart';
import '../../core/data/services/playlist_controller.dart';
import '../../core/theme/app_colors.dart';
import '../../core/widgets/empty_state.dart';
import '../../l10n/app_localizations.dart';
@@ -23,6 +26,7 @@ class RecommendPage extends StatefulWidget {
const RecommendPage({
super.key,
required this.feedController,
this.catalogApi,
required this.active,
required this.onSearch,
this.videoOnly = false,
@@ -30,6 +34,7 @@ class RecommendPage extends StatefulWidget {
});
final HomeFeedController feedController;
final CatalogApi? catalogApi;
final bool active;
final VoidCallback onSearch;
@@ -46,6 +51,32 @@ class _RecommendPageState extends State<RecommendPage> {
final PageController _pageController = PageController();
int _scrubCancelRequest = 0;
@override
void initState() {
super.initState();
if (widget.active) _scheduleRecommendData();
}
@override
void didUpdateWidget(RecommendPage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.active && !oldWidget.active) _scheduleRecommendData();
}
void _scheduleRecommendData() {
final feed = widget.feedController;
if (!feed.loaded && !feed.loadingFirstPage) {
unawaited(feed.refreshCurrent());
}
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || !widget.active) return;
final playlists = _readPlaylists();
if (playlists != null && !playlists.loaded && !playlists.loading) {
unawaited(playlists.load());
}
});
}
@override
void dispose() {
_pageController.dispose();
@@ -82,6 +113,7 @@ class _RecommendPageState extends State<RecommendPage> {
child: _withTopNavSpace(
AllDramasFilterGrid(
feedController: widget.feedController,
catalogApi: widget.catalogApi,
onOpenDrama: _openDrama,
),
),
@@ -168,6 +200,22 @@ class _RecommendPageState extends State<RecommendPage> {
);
}
PlaylistController? _watchPlaylists(BuildContext context) {
try {
return context.watch<PlaylistController>();
} on ProviderNotFoundException {
return null;
}
}
PlaylistController? _readPlaylists() {
try {
return context.read<PlaylistController>();
} on ProviderNotFoundException {
return null;
}
}
Widget _recommendPlaylists(CategoryController categories) {
return DecoratedBox(
key: const Key('recommend-playlist-surface'),
@@ -205,6 +253,8 @@ class _RecommendPageState extends State<RecommendPage> {
categories: categories,
onOpenDrama: _openDrama,
onMore: _handleMore,
playlists: _watchPlaylists(context),
onOpenPlaylist: _openPlaylist,
),
),
],
@@ -252,6 +302,36 @@ class _RecommendPageState extends State<RecommendPage> {
);
}
Future<void> _openPlaylist(PlaylistDetail playlist) async {
final controller = _readPlaylists();
const pageSize = CatalogApi.playlistDramaPageSize;
final fresh = controller == null
? playlist
: await controller.detail(playlist.id, pageSize: pageSize);
if (!mounted) return;
final shown = fresh.dramas.isEmpty && playlist.dramas.isNotEmpty
? playlist
: fresh;
await Navigator.of(context).push<void>(
MaterialPageRoute<void>(
builder: (_) => PlaylistDetailPage(
title: shown.name,
subtitle: shown.description,
source: shown,
dramas: shown.dramas,
dramaCount: shown.dramaCount,
loadPage: controller == null
? null
: (pageIndex) => controller.detail(
playlist.id,
pageIndex: pageIndex,
pageSize: pageSize,
),
),
),
);
}
void _handleMore(RecommendSectionKind section) {
final l10n = AppLocalizations.of(context)!;
final copy = _sectionCopy(l10n, section);