Improve categories page.

This commit is contained in:
2025-10-13 20:28:03 +08:00
parent 3426d707fe
commit 49fd64358c

View File

@@ -17,39 +17,50 @@ class CategoriesPage extends StatefulWidget {
State<CategoriesPage> createState() => _CategoriesPageState();
}
class _CategoriesPageState extends State<CategoriesPage> {
class _CategoriesPageState extends State<CategoriesPage>
with
TickerProviderStateMixin,
AutomaticKeepAliveClientMixin<CategoriesPage> {
var categories = <String>[];
late TabController controller;
void onSettingsChanged() {
var categories =
List.from(appdata.settings["categories"]).whereType<String>().toList();
var categories = List.from(
appdata.settings["categories"],
).whereType<String>().toList();
var allCategories = ComicSource.all()
.map((e) => e.categoryData?.key)
.where((element) => element != null)
.map((e) => e!)
.toList();
categories =
categories.where((element) => allCategories.contains(element)).toList();
categories = categories
.where((element) => allCategories.contains(element))
.toList();
if (!categories.isEqualTo(this.categories)) {
setState(() {
this.categories = categories;
});
controller = TabController(length: categories.length, vsync: this);
}
}
@override
void initState() {
super.initState();
var categories =
List.from(appdata.settings["categories"]).whereType<String>().toList();
var categories = List.from(
appdata.settings["categories"],
).whereType<String>().toList();
var allCategories = ComicSource.all()
.map((e) => e.categoryData?.key)
.where((element) => element != null)
.map((e) => e!)
.toList();
this.categories =
categories.where((element) => allCategories.contains(element)).toList();
this.categories = categories
.where((element) => allCategories.contains(element))
.toList();
appdata.settings.addListener(onSettingsChanged);
controller = TabController(length: categories.length, vsync: this);
}
void addPage() {
@@ -59,6 +70,7 @@ class _CategoriesPageState extends State<CategoriesPage> {
@override
void dispose() {
super.dispose();
controller.dispose();
appdata.settings.removeListener(onSettingsChanged);
}
@@ -85,46 +97,45 @@ class _CategoriesPageState extends State<CategoriesPage> {
@override
Widget build(BuildContext context) {
super.build(context);
if (categories.isEmpty) {
return buildEmpty();
}
return Material(
child: DefaultTabController(
length: categories.length,
key: Key(categories.toString()),
child: Column(
children: [
AppTabBar(
key: PageStorageKey(categories.toString()),
tabs: categories.map((e) {
String title = e;
try {
title = getCategoryDataWithKey(e).title;
} catch (e) {
//
}
return Tab(
text: title,
key: Key(e),
);
}).toList(),
actionButton: TabActionButton(
icon: const Icon(Icons.add),
text: "Add".tl,
onPressed: addPage,
),
).paddingTop(context.padding.top),
Expanded(
child: TabBarView(
children: categories.map((e) => _CategoryPage(e)).toList(),
),
)
],
),
child: Column(
children: [
AppTabBar(
controller: controller,
key: PageStorageKey(categories.toString()),
tabs: categories.map((e) {
String title = e;
try {
title = getCategoryDataWithKey(e).title;
} catch (e) {
//
}
return Tab(text: title, key: Key(e));
}).toList(),
actionButton: TabActionButton(
icon: const Icon(Icons.add),
text: "Add".tl,
onPressed: addPage,
),
).paddingTop(context.padding.top),
Expanded(
child: TabBarView(
controller: controller,
children: categories.map((e) => _CategoryPage(e)).toList(),
),
),
],
),
);
}
@override
bool get wantKeepAlive => true;
}
typedef ClickTagCallback = void Function(String, String?);
@@ -150,38 +161,42 @@ class _CategoryPage extends StatelessWidget {
var children = <Widget>[];
if (data.enableRankingPage || data.buttons.isNotEmpty) {
children.add(buildTitle(data.title));
children.add(Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 16),
child: Wrap(
children: [
if (data.enableRankingPage)
buildTag("Ranking".tl, () {
context.to(() => RankingPage(categoryKey: data.key));
}),
for (var buttonData in data.buttons)
buildTag(buttonData.label.tl, buttonData.onTap)
],
children.add(
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 16),
child: Wrap(
children: [
if (data.enableRankingPage)
buildTag("Ranking".tl, () {
context.to(() => RankingPage(categoryKey: data.key));
}),
for (var buttonData in data.buttons)
buildTag(buttonData.label.tl, buttonData.onTap),
],
),
),
));
);
}
for (var part in data.categories) {
if (part.enableRandom) {
children.add(StatefulBuilder(builder: (context, updater) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildTitleWithRefresh(part.title, () => updater(() {})),
buildTags(part.categories)
],
);
}));
children.add(
StatefulBuilder(
builder: (context, updater) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildTitleWithRefresh(part.title, () => updater(() {})),
buildTags(part.categories),
],
);
},
),
);
} else {
children.add(buildTitle(part.title));
children.add(
buildTags(part.categories),
);
children.add(buildTags(part.categories));
}
}
return SingleChildScrollView(
@@ -195,8 +210,10 @@ class _CategoryPage extends StatelessWidget {
Widget buildTitle(String title) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 10, 5, 10),
child: Text(title.tl,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500)),
child: Text(
title.tl,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
);
}
@@ -207,21 +224,16 @@ class _CategoryPage extends StatelessWidget {
children: [
Text(
title.tl,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
const Spacer(),
IconButton(onPressed: onRefresh, icon: const Icon(Icons.refresh))
IconButton(onPressed: onRefresh, icon: const Icon(Icons.refresh)),
],
),
);
}
Widget buildTags(
List<CategoryItem> categories,
) {
Widget buildTags(List<CategoryItem> categories) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 16),
child: Wrap(