fix(home): 修正首页分类与卡片布局
This commit is contained in:
1 parent
10477562d4
commit
aa4870cce6
14 files changed
+573
-459
No files matched your search
@@ -36,6 +36,8 @@ class AllDramasFilterGrid extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
String _region = 'all';
|
||||
String _audio = 'all';
|
||||
String? _genre;
|
||||
bool _newest = false;
|
||||
|
||||
@@ -71,7 +73,11 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
icon: Icons.movie_filter_outlined,
|
||||
title: l10n.homeGridFilterEmpty,
|
||||
actionLabel: l10n.homeGridClearFilter,
|
||||
onAction: () => setState(() => _genre = null),
|
||||
onAction: () => setState(() {
|
||||
_region = 'all';
|
||||
_audio = 'all';
|
||||
_genre = null;
|
||||
}),
|
||||
),
|
||||
)
|
||||
else
|
||||
@@ -130,12 +136,28 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
child: Column(
|
||||
key: const Key('all-dramas-filters'),
|
||||
children: [
|
||||
_chipRow(0, [l10n.all]),
|
||||
_chipRow(1, [l10n.all]),
|
||||
_chipRow(2, [
|
||||
(id: null, label: l10n.all),
|
||||
for (final genre in genres) (id: genre.id, label: genre.label),
|
||||
]),
|
||||
_selectableRow(
|
||||
0,
|
||||
[
|
||||
(id: 'all', label: l10n.all),
|
||||
(id: 'local', label: l10n.localFilter),
|
||||
(id: 'asia', label: l10n.asiaFilter),
|
||||
(id: 'western', label: l10n.westernFilter),
|
||||
],
|
||||
selected: _region,
|
||||
onSelected: (value) => setState(() => _region = value),
|
||||
),
|
||||
_selectableRow(
|
||||
1,
|
||||
[
|
||||
(id: 'all', label: l10n.all),
|
||||
(id: 'subtitles', label: l10n.subtitlesOnlyFilter),
|
||||
(id: 'dubbed', label: l10n.dubbedFilter),
|
||||
],
|
||||
selected: _audio,
|
||||
onSelected: (value) => setState(() => _audio = value),
|
||||
),
|
||||
_genreRow(2, genres, l10n),
|
||||
Row(
|
||||
key: const Key('all-filter-row-3'),
|
||||
children: [
|
||||
@@ -173,7 +195,12 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _chipRow(int row, List<Object> options) {
|
||||
Widget _selectableRow(
|
||||
int row,
|
||||
List<({String id, String label})> options, {
|
||||
required String selected,
|
||||
required ValueChanged<String> onSelected,
|
||||
}) {
|
||||
return Padding(
|
||||
key: Key('all-filter-row-$row'),
|
||||
padding: const EdgeInsets.only(bottom: AppDimens.spaceSm),
|
||||
@@ -182,14 +209,12 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
child: Row(
|
||||
children: [
|
||||
for (final option in options) ...[
|
||||
if (option is String)
|
||||
_chip(label: option, selected: true, onTap: () {}),
|
||||
if (option is ({String? id, String label}))
|
||||
_chip(
|
||||
label: option.label,
|
||||
selected: _genre == option.id,
|
||||
onTap: () => setState(() => _genre = option.id),
|
||||
),
|
||||
_chip(
|
||||
key: Key('all-filter-${option.id}'),
|
||||
label: option.label,
|
||||
selected: selected == option.id,
|
||||
onTap: () => onSelected(option.id),
|
||||
),
|
||||
const SizedBox(width: AppDimens.spaceSm),
|
||||
],
|
||||
],
|
||||
@@ -198,6 +223,23 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _genreRow(
|
||||
int row,
|
||||
List<({String id, String label})> options,
|
||||
AppLocalizations l10n,
|
||||
) {
|
||||
return _selectableRow(
|
||||
row,
|
||||
[
|
||||
(id: 'all', label: l10n.all),
|
||||
for (final genre in options) (id: genre.id, label: genre.label),
|
||||
],
|
||||
selected: _genre ?? 'all',
|
||||
onSelected: (value) =>
|
||||
setState(() => _genre = value == 'all' ? null : value),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _chip({
|
||||
Key? key,
|
||||
required String label,
|
||||
@@ -248,6 +290,7 @@ class _AllDramasFilterGridState extends State<AllDramasFilterGrid> {
|
||||
}
|
||||
|
||||
List<Drama> _filtered() {
|
||||
if (_region != 'all' || _audio != 'all') return const [];
|
||||
final dramas = widget.feedController.dramas
|
||||
.where((drama) {
|
||||
return _genre == null || _matchesGenre(drama, _genre!, const []);
|
||||
|
||||
@@ -35,6 +35,7 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
onTap: onTap,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ClipRRect(
|
||||
@@ -83,6 +84,8 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
const SizedBox(height: AppDimens.cardCoverTitleGap),
|
||||
Row(
|
||||
key: Key('recommend-views-$sectionKey-${drama.id}'),
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.play_arrow_rounded,
|
||||
@@ -123,38 +126,16 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
|
||||
Widget _tags() {
|
||||
final tags = _cardTags();
|
||||
return Row(
|
||||
children: [
|
||||
for (final (index, tag) in tags.indexed)
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: index == tags.length - 1 ? 0 : AppDimens.spaceXs,
|
||||
),
|
||||
child: Container(
|
||||
key: Key('recommend-tag-$sectionKey-${drama.id}-$index'),
|
||||
height: AppDimens.cardTagHeight,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppDimens.cardTagHorizontalPadding,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.contentSurface,
|
||||
borderRadius: BorderRadius.circular(AppDimens.cardTagRadius),
|
||||
),
|
||||
child: Text(
|
||||
tag,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textTertiary,
|
||||
fontSize: AppDimens.cardTagFont,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
return Text(
|
||||
tags.join(' | '),
|
||||
key: Key('recommend-tags-$sectionKey-${drama.id}'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textTertiary,
|
||||
fontSize: AppDimens.cardTagFont,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -164,7 +145,7 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
.expand((value) => value.split(_tagSplitter))
|
||||
.map((value) => value.trim())
|
||||
.where((value) => value.isNotEmpty && seen.add(value))
|
||||
.take(2)
|
||||
.take(3)
|
||||
.toList(growable: false);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user