Add dynamic category part.

This commit is contained in:
2025-04-05 20:11:05 +08:00
parent 554b9f2a77
commit c096f5a2d8
3 changed files with 59 additions and 6 deletions

View File

@@ -97,6 +97,43 @@ class RandomCategoryPart extends BaseCategoryPart {
);
}
class DynamicCategoryPart extends BaseCategoryPart {
final JSAutoFreeFunction loader;
final String sourceKey;
@override
List<CategoryItem> get categories {
var data = loader([]);
print(data);
if (data is! List) {
throw "DynamicCategoryPart loader must return a List";
}
var res = <CategoryItem>[];
for (var item in data) {
if (item is! Map) {
throw "DynamicCategoryPart loader must return a List of Map";
}
var label = item['label'];
var target = PageJumpTarget.parse(sourceKey, item['target']);
if (label is! String) {
throw "Category label must be a String";
}
res.add(CategoryItem(label, target));
}
return res;
}
@override
bool get enableRandom => false;
@override
final String title;
/// A [BaseCategoryPart] that show dynamic tags on category page.
const DynamicCategoryPart(this.title, this.loader, this.sourceKey);
}
CategoryData getCategoryDataWithKey(String key) {
for (var source in ComicSource.all()) {
if (source.categoryData?.key == key) {

View File

@@ -403,27 +403,40 @@ class ComicSourceParser {
var categoryParts = <BaseCategoryPart>[];
for (var c in doc["parts"]) {
if (c["categories"] is! List || c["categories"].isEmpty) {
if (c["categories"] != null && c["categories"] is! List) {
continue;
}
List categories = c["categories"];
if (categories[0] is Map) {
List? categories = c["categories"];
if (categories == null || categories[0] is Map) {
// new format
final String name = c["name"];
final String type = c["type"];
final cs = categories
.map(
?.map(
(e) => CategoryItem(
e['label'],
PageJumpTarget.parse(_key!, e['target']),
),
)
.toList();
if (type != "dynamic" && (cs == null || cs.isEmpty)) {
continue;
}
if (type == "fixed") {
categoryParts.add(FixedCategoryPart(name, cs));
categoryParts.add(FixedCategoryPart(name, cs!));
} else if (type == "random") {
categoryParts
.add(RandomCategoryPart(name, cs, c["randomNumber"] ?? 1));
.add(RandomCategoryPart(name, cs!, c["randomNumber"] ?? 1));
} else if (type == "dynamic" && categories == null) {
var loader = c["loader"];
if (loader is! JSInvokable) {
throw "DynamicCategoryPart loader must be a function";
}
categoryParts.add(DynamicCategoryPart(
name,
JSAutoFreeFunction(loader),
_key!,
));
}
} else {
// old format

View File

@@ -34,6 +34,9 @@ class _CategoryComicsPageState extends State<CategoryComicsPage> {
void findData() {
for (final source in ComicSource.all()) {
if (source.categoryData?.key == widget.categoryKey) {
if (source.categoryComicsData == null) {
throw "The comic source ${source.name} does not support category comics";
}
data = source.categoryComicsData!;
options = data.options.where((element) {
if (element.notShowWhen.contains(widget.category)) {