mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
add loginWithWebview, mixed explore page, app links, html node api;
improve ui
This commit is contained in:
@@ -88,7 +88,8 @@ class RandomCategoryPart extends BaseCategoryPart {
|
||||
if (randomNumber >= tags.length) {
|
||||
return tags;
|
||||
}
|
||||
return tags.sublist(math.Random().nextInt(tags.length - randomNumber));
|
||||
var start = math.Random().nextInt(tags.length - randomNumber);
|
||||
return tags.sublist(start, start + randomNumber);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@@ -197,6 +197,8 @@ class ComicSource {
|
||||
|
||||
final HandleClickTagEvent? handleClickTagEvent;
|
||||
|
||||
final LinkHandler? linkHandler;
|
||||
|
||||
Future<void> loadData() async {
|
||||
var file = File("${App.dataPath}/comic_source/$key.data");
|
||||
if (await file.exists()) {
|
||||
@@ -261,14 +263,13 @@ class ComicSource {
|
||||
this.idMatcher,
|
||||
this.translations,
|
||||
this.handleClickTagEvent,
|
||||
this.linkHandler,
|
||||
);
|
||||
}
|
||||
|
||||
class AccountConfig {
|
||||
final LoginFunction? login;
|
||||
|
||||
final FutureOr<void> Function(BuildContext)? onLogin;
|
||||
|
||||
final String? loginWebsite;
|
||||
|
||||
final String? registerWebsite;
|
||||
@@ -279,10 +280,15 @@ class AccountConfig {
|
||||
|
||||
final List<AccountInfoItem> infoItems;
|
||||
|
||||
final bool Function(String url, String title)? checkLoginStatus;
|
||||
|
||||
const AccountConfig(
|
||||
this.login, this.loginWebsite, this.registerWebsite, this.logout,
|
||||
{this.onLogin})
|
||||
: allowReLogin = true,
|
||||
this.login,
|
||||
this.loginWebsite,
|
||||
this.registerWebsite,
|
||||
this.logout,
|
||||
this.checkLoginStatus,
|
||||
) : allowReLogin = true,
|
||||
infoItems = const [];
|
||||
}
|
||||
|
||||
@@ -315,11 +321,13 @@ class ExplorePageData {
|
||||
/// return a `List` contains `List<Comic>` or `ExplorePagePart`
|
||||
final Future<Res<List<Object>>> Function(int index)? loadMixed;
|
||||
|
||||
final WidgetBuilder? overridePageBuilder;
|
||||
|
||||
ExplorePageData(this.title, this.type, this.loadPage, this.loadMultiPart)
|
||||
: loadMixed = null,
|
||||
overridePageBuilder = null;
|
||||
ExplorePageData(
|
||||
this.title,
|
||||
this.type,
|
||||
this.loadPage,
|
||||
this.loadMultiPart,
|
||||
this.loadMixed,
|
||||
);
|
||||
}
|
||||
|
||||
class ExplorePagePart {
|
||||
@@ -422,3 +430,12 @@ class CategoryComicsOptions {
|
||||
|
||||
const CategoryComicsOptions(this.options, this.notShowWhen, this.showWhen);
|
||||
}
|
||||
|
||||
|
||||
class LinkHandler {
|
||||
final List<String> domains;
|
||||
|
||||
final String? Function(String url) linkToId;
|
||||
|
||||
const LinkHandler(this.domains, this.linkToId);
|
||||
}
|
@@ -11,11 +11,23 @@ class Comment {
|
||||
final bool? isLiked;
|
||||
final int? voteStatus; // 1: upvote, -1: downvote, 0: none
|
||||
|
||||
static String? parseTime(dynamic value) {
|
||||
if(value == null) return null;
|
||||
if(value is int) {
|
||||
if(value < 10000000000) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(value * 1000).toString().substring(0, 19);
|
||||
} else {
|
||||
return DateTime.fromMillisecondsSinceEpoch(value).toString().substring(0, 19);
|
||||
}
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
Comment.fromJson(Map<String, dynamic> json)
|
||||
: userName = json["userName"],
|
||||
avatar = json["avatar"],
|
||||
content = json["content"],
|
||||
time = json["time"],
|
||||
time = parseTime(json["time"]),
|
||||
replyCount = json["replyCount"],
|
||||
id = json["id"].toString(),
|
||||
score = json["score"],
|
||||
@@ -40,8 +52,19 @@ class Comic {
|
||||
|
||||
final int? maxPage;
|
||||
|
||||
const Comic(this.title, this.cover, this.id, this.subtitle, this.tags,
|
||||
this.description, this.sourceKey, this.maxPage);
|
||||
final String? language;
|
||||
|
||||
const Comic(
|
||||
this.title,
|
||||
this.cover,
|
||||
this.id,
|
||||
this.subtitle,
|
||||
this.tags,
|
||||
this.description,
|
||||
this.sourceKey,
|
||||
this.maxPage,
|
||||
this.language,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
@@ -53,6 +76,7 @@ class Comic {
|
||||
"description": description,
|
||||
"sourceKey": sourceKey,
|
||||
"maxPage": maxPage,
|
||||
"language": language,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,7 +87,8 @@ class Comic {
|
||||
id = json["id"],
|
||||
tags = List<String>.from(json["tags"] ?? []),
|
||||
description = json["description"] ?? "",
|
||||
maxPage = json["maxPage"];
|
||||
maxPage = json["maxPage"],
|
||||
language = json["language"];
|
||||
}
|
||||
|
||||
class ComicDetails with HistoryMixin {
|
||||
@@ -109,7 +134,7 @@ class ComicDetails with HistoryMixin {
|
||||
|
||||
final String? url;
|
||||
|
||||
static Map<String, List<String>> _generateMap(Map<String, dynamic> map) {
|
||||
static Map<String, List<String>> _generateMap(Map<dynamic, dynamic> map) {
|
||||
var res = <String, List<String>>{};
|
||||
map.forEach((key, value) {
|
||||
res[key] = List<String>.from(value);
|
||||
|
@@ -147,6 +147,7 @@ class ComicSourceParser {
|
||||
_parseIdMatch(),
|
||||
_parseTranslation(),
|
||||
_parseClickTagEvent(),
|
||||
_parseLinkHandler(),
|
||||
);
|
||||
|
||||
await source.loadData();
|
||||
@@ -199,8 +200,28 @@ class ComicSourceParser {
|
||||
JsEngine().runCode("ComicSource.sources.$_key.account.logout()");
|
||||
}
|
||||
|
||||
return AccountConfig(login, _getValue("account.login.website"),
|
||||
_getValue("account.registerWebsite"), logout);
|
||||
if(!_checkExists('account.loginWithWebview')) {
|
||||
return AccountConfig(
|
||||
login,
|
||||
null,
|
||||
_getValue("account.registerWebsite"),
|
||||
logout,
|
||||
null,
|
||||
);
|
||||
} else {
|
||||
return AccountConfig(
|
||||
null,
|
||||
_getValue("account.loginWithWebview.url"),
|
||||
_getValue("account.registerWebsite"),
|
||||
logout,
|
||||
(url, title) {
|
||||
return JsEngine().runCode("""
|
||||
ComicSource.sources.$_key.account.loginWithWebview.checkStatus(
|
||||
${jsonEncode(url)}, ${jsonEncode(title)})
|
||||
""");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<ExplorePageData> _loadExploreData() {
|
||||
@@ -214,6 +235,7 @@ class ComicSourceParser {
|
||||
final String type = _getValue("explore[$i].type");
|
||||
Future<Res<List<ExplorePagePart>>> Function()? loadMultiPart;
|
||||
Future<Res<List<Comic>>> Function(int page)? loadPage;
|
||||
Future<Res<List<Object>>> Function(int index)? loadMixed;
|
||||
if (type == "singlePageWithMultiPart") {
|
||||
loadMultiPart = () async {
|
||||
try {
|
||||
@@ -246,18 +268,69 @@ class ComicSourceParser {
|
||||
return Res.error(e.toString());
|
||||
}
|
||||
};
|
||||
} else if (type == "multiPartPage") {
|
||||
loadMultiPart = () async {
|
||||
try {
|
||||
var res = await JsEngine()
|
||||
.runCode("ComicSource.sources.$_key.explore[$i].load()");
|
||||
return Res(
|
||||
List.from(
|
||||
(res as List).map((e) {
|
||||
return ExplorePagePart(
|
||||
e['title'],
|
||||
(e['comics'] as List).map((e) {
|
||||
return Comic.fromJson(e, _key!);
|
||||
}).toList(),
|
||||
e['viewMore'],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Log.error("Data Analysis", "$e\n$s");
|
||||
return Res.error(e.toString());
|
||||
}
|
||||
};
|
||||
} else if (type == 'mixed') {
|
||||
loadMixed = (index) async {
|
||||
try {
|
||||
var res = await JsEngine().runCode(
|
||||
"ComicSource.sources.$_key.explore[$i].load(${jsonEncode(index)})");
|
||||
var list = <Object>[];
|
||||
for (var data in (res['data'] as List)) {
|
||||
if (data is List) {
|
||||
list.add(data.map((e) => Comic.fromJson(e, _key!)).toList());
|
||||
} else if (data is Map) {
|
||||
list.add(ExplorePagePart(
|
||||
data['title'],
|
||||
(data['comics'] as List).map((e) {
|
||||
return Comic.fromJson(e, _key!);
|
||||
}).toList(),
|
||||
data['viewMore'],
|
||||
));
|
||||
}
|
||||
}
|
||||
return Res(list, subData: res['maxPage']);
|
||||
} catch (e, s) {
|
||||
Log.error("Network", "$e\n$s");
|
||||
return Res.error(e.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
pages.add(ExplorePageData(
|
||||
title,
|
||||
switch (type) {
|
||||
"singlePageWithMultiPart" =>
|
||||
ExplorePageType.singlePageWithMultiPart,
|
||||
"multiPageComicList" => ExplorePageType.multiPageComicList,
|
||||
_ =>
|
||||
throw ComicSourceParseException("Unknown explore page type $type")
|
||||
},
|
||||
loadPage,
|
||||
loadMultiPart));
|
||||
title,
|
||||
switch (type) {
|
||||
"singlePageWithMultiPart" => ExplorePageType.singlePageWithMultiPart,
|
||||
"multiPartPage" => ExplorePageType.singlePageWithMultiPart,
|
||||
"multiPageComicList" => ExplorePageType.multiPageComicList,
|
||||
"mixed" => ExplorePageType.mixed,
|
||||
_ =>
|
||||
throw ComicSourceParseException("Unknown explore page type $type")
|
||||
},
|
||||
loadPage,
|
||||
loadMultiPart,
|
||||
loadMixed,
|
||||
));
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
@@ -279,8 +352,11 @@ class ComicSourceParser {
|
||||
final String type = c["type"];
|
||||
final List<String> tags = List.from(c["categories"]);
|
||||
final String itemType = c["itemType"];
|
||||
final List<String>? categoryParams =
|
||||
c["categoryParams"] == null ? null : List.from(c["categoryParams"]);
|
||||
List<String>? categoryParams = ListOrNull.from(c["categoryParams"]);
|
||||
final String? groupParam = c["groupParam"];
|
||||
if (groupParam != null) {
|
||||
categoryParams = List.filled(tags.length, groupParam);
|
||||
}
|
||||
if (type == "fixed") {
|
||||
categoryParts
|
||||
.add(FixedCategoryPart(name, tags, itemType, categoryParams));
|
||||
@@ -407,6 +483,7 @@ class ComicSourceParser {
|
||||
if (res is! Map<String, dynamic>) throw "Invalid data";
|
||||
res['comicId'] = id;
|
||||
res['sourceKey'] = _key;
|
||||
JsEngine().clearHtml();
|
||||
return Res(ComicDetails.fromJson(res));
|
||||
} catch (e, s) {
|
||||
Log.error("Network", "$e\n$s");
|
||||
@@ -728,4 +805,18 @@ class ComicSourceParser {
|
||||
return Map.from(r);
|
||||
};
|
||||
}
|
||||
|
||||
LinkHandler? _parseLinkHandler() {
|
||||
if (!_checkExists("linkHandler")) {
|
||||
return null;
|
||||
}
|
||||
List<String> domains = List.from(_getValue("link.domains"));
|
||||
linkToId(String link) {
|
||||
var res = JsEngine().runCode("""
|
||||
ComicSource.sources.$_key.link.linkToId(${jsonEncode(link)})
|
||||
""");
|
||||
return res as String?;
|
||||
}
|
||||
return LinkHandler(domains, linkToId);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user