feat(app): 客户端展示多语言并支持筛选分页
This commit is contained in:
1 parent
8481611372
commit
8b50b5bd06
68 files changed
+2742
-1120
No files matched your search
@@ -20,11 +20,13 @@ class HomeGridCategoryShortcut {
|
||||
const HomeGridCategoryShortcut({
|
||||
required this.label,
|
||||
required this.categoryName,
|
||||
required this.categoryId,
|
||||
required this.tab,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final String categoryName;
|
||||
final String categoryId;
|
||||
final HomePrimaryTab tab;
|
||||
}
|
||||
|
||||
@@ -47,15 +49,15 @@ class HomeGridHeader extends StatelessWidget {
|
||||
super.key,
|
||||
required this.callbacks,
|
||||
required this.categories,
|
||||
required this.selectedPrimary,
|
||||
required this.onPrimarySelected,
|
||||
required this.selectedIndex,
|
||||
required this.onSectionSelected,
|
||||
this.walletBadge,
|
||||
});
|
||||
|
||||
final HomeGridCallbacks callbacks;
|
||||
final List<HomeGridCategoryShortcut> categories;
|
||||
final HomePrimaryTab selectedPrimary;
|
||||
final ValueChanged<HomePrimaryTab> onPrimarySelected;
|
||||
final int selectedIndex;
|
||||
final ValueChanged<int> onSectionSelected;
|
||||
final int? walletBadge;
|
||||
|
||||
@override
|
||||
@@ -67,7 +69,7 @@ class HomeGridHeader extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
_searchRow(l10n),
|
||||
_primaryRow(l10n),
|
||||
_primaryRow(),
|
||||
const SizedBox(height: AppDimens.homeSecondaryGridGap),
|
||||
],
|
||||
);
|
||||
@@ -225,7 +227,73 @@ class HomeGridHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _primaryRow(AppLocalizations l10n) {
|
||||
Widget _primaryRow() {
|
||||
return _CategoryBar(
|
||||
categories: categories,
|
||||
selectedIndex: selectedIndex,
|
||||
onSectionSelected: onSectionSelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CategoryBar extends StatefulWidget {
|
||||
const _CategoryBar({
|
||||
required this.categories,
|
||||
required this.selectedIndex,
|
||||
required this.onSectionSelected,
|
||||
});
|
||||
|
||||
final List<HomeGridCategoryShortcut> categories;
|
||||
final int selectedIndex;
|
||||
final ValueChanged<int> onSectionSelected;
|
||||
|
||||
@override
|
||||
State<_CategoryBar> createState() => _CategoryBarState();
|
||||
}
|
||||
|
||||
class _CategoryBarState extends State<_CategoryBar> {
|
||||
final List<GlobalKey> _itemKeys = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_syncKeys();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _revealSelected());
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(_CategoryBar oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.categories.length != widget.categories.length) {
|
||||
_syncKeys();
|
||||
}
|
||||
if (oldWidget.selectedIndex != widget.selectedIndex ||
|
||||
oldWidget.categories.length != widget.categories.length) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _revealSelected());
|
||||
}
|
||||
}
|
||||
|
||||
void _syncKeys() {
|
||||
_itemKeys
|
||||
..clear()
|
||||
..addAll(List.generate(widget.categories.length, (_) => GlobalKey()));
|
||||
}
|
||||
|
||||
void _revealSelected() {
|
||||
final index = widget.selectedIndex;
|
||||
if (!mounted || index < 0 || index >= _itemKeys.length) return;
|
||||
final target = _itemKeys[index].currentContext;
|
||||
if (target == null) return;
|
||||
Scrollable.ensureVisible(
|
||||
target,
|
||||
alignment: 0.5,
|
||||
duration: AppDimens.homePrimaryTabAnimationDuration,
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
key: const Key('home-primary-sections'),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@@ -234,60 +302,29 @@ class HomeGridHeader extends StatelessWidget {
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
_primaryItem(
|
||||
key: const Key('home-section-featured'),
|
||||
label: l10n.homeSectionFeatured,
|
||||
tab: HomePrimaryTab.featured,
|
||||
),
|
||||
_primaryItem(
|
||||
key: const Key('home-section-new'),
|
||||
label: l10n.homeSectionNew,
|
||||
tab: HomePrimaryTab.newReleases,
|
||||
),
|
||||
_primaryItem(
|
||||
key: const Key('home-section-categories'),
|
||||
label: l10n.homeSectionCategories,
|
||||
tab: HomePrimaryTab.categories,
|
||||
),
|
||||
_primaryItem(
|
||||
key: const Key('home-section-ranking'),
|
||||
label: l10n.homeSectionRanking,
|
||||
tab: HomePrimaryTab.ranking,
|
||||
),
|
||||
for (final category in categories)
|
||||
_primaryItem(
|
||||
key: Key(
|
||||
category.categoryName.isEmpty
|
||||
? 'home-section-${category.tab.name}'
|
||||
: 'home-section-category-${category.categoryName}',
|
||||
),
|
||||
label: category.label,
|
||||
tab: category.tab,
|
||||
),
|
||||
for (var index = 0; index < widget.categories.length; index++)
|
||||
_item(index),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _primaryItem({
|
||||
required Key key,
|
||||
required String label,
|
||||
required HomePrimaryTab tab,
|
||||
}) {
|
||||
final selected = selectedPrimary == tab;
|
||||
Widget _item(int index) {
|
||||
final category = widget.categories[index];
|
||||
final selected = widget.selectedIndex == index;
|
||||
return InkWell(
|
||||
key: key,
|
||||
onTap: () => onPrimarySelected(tab),
|
||||
key: _itemKeys[index],
|
||||
onTap: () => widget.onSectionSelected(index),
|
||||
child: Padding(
|
||||
key: Key('home-section-category-${category.categoryName}'),
|
||||
padding: const EdgeInsets.only(right: AppDimens.homePrimaryCategoryGap),
|
||||
child: SizedBox(
|
||||
height: AppDimens.homePrimaryRowHeight,
|
||||
child: Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: AnimatedDefaultTextStyle(
|
||||
key: Key('home-primary-label-${tab.name}'),
|
||||
key: Key('home-primary-label-${category.categoryId}'),
|
||||
duration: AppDimens.homePrimaryTabAnimationDuration,
|
||||
curve: Curves.easeOut,
|
||||
style: TextStyle(
|
||||
@@ -300,7 +337,7 @@ class HomeGridHeader extends StatelessWidget {
|
||||
fontWeight: selected ? FontWeight.w700 : FontWeight.w400,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
child: Text(label, textAlign: TextAlign.left),
|
||||
child: Text(category.label, textAlign: TextAlign.left),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user