add comment
This commit is contained in:
parent
8096f517a2
commit
088453f1ad
|
@ -92,9 +92,6 @@ class MainActivity : FlutterActivity() {
|
|||
setMode(call.argument("mode")!!)
|
||||
}
|
||||
"androidGetVersion" -> Build.VERSION.SDK_INT
|
||||
// "exportComicDownloadAndroidQ" -> {
|
||||
// exportComicDownloadAndroidQ(call.argument("comicId")!!)
|
||||
// }
|
||||
// 现在的文件储存路径, 默认路径返回空字符串 ""
|
||||
"dataLocal" -> androidDataLocal()
|
||||
// 迁移到那个地方, 如果是空字符串则迁移会默认位置
|
||||
|
@ -341,63 +338,4 @@ class MainActivity : FlutterActivity() {
|
|||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
// 安卓11以上使用了 MANAGE_EXTERNAL_STORAGE 权限来管理整个外置存储 (危险权限)
|
||||
// private val resourceQueue: LinkedBlockingQueue<Any?> = LinkedBlockingQueue()
|
||||
// private var tmpComicId: String? = null
|
||||
// private val exportComicDownloadAndroidQRequestCode = 2
|
||||
//
|
||||
// private fun exportComicDownloadAndroidQ(comicId: String) {
|
||||
// val title = Mobile.flatInvoke("specialDownloadTitle", comicId)
|
||||
// var fileName = title
|
||||
// fileName = fileName.replace('/', '_')
|
||||
// fileName = fileName.replace('\\', '_')
|
||||
// fileName = fileName.replace('*', '_')
|
||||
// fileName = fileName.replace('?', '_')
|
||||
// fileName = fileName.replace('<', '_')
|
||||
// fileName = fileName.replace('>', '_')
|
||||
// fileName = fileName.replace('|', '_')
|
||||
// fileName = fileName + "_" + System.currentTimeMillis() + ".zip"
|
||||
// tmpComicId = comicId
|
||||
// startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).also {
|
||||
// it.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
// it.type = "application/octet-stream"
|
||||
// it.putExtra(Intent.EXTRA_TITLE, fileName)
|
||||
// }, exportComicDownloadAndroidQRequestCode)
|
||||
// val result = resourceQueue.take()
|
||||
// if (result is Throwable) {
|
||||
// throw result
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
// pool.submit {
|
||||
// try {
|
||||
// if (resultCode === RESULT_OK && data != null) {
|
||||
// when (requestCode) {
|
||||
// exportComicDownloadAndroidQRequestCode -> {
|
||||
// contentResolver.openOutputStream(data.data!!)?.use { os ->
|
||||
// val path = Mobile.flatInvoke("exportComicDownload", Gson().toJson(HashMap<Any, Any?>().also { map ->
|
||||
// map["comicId"] = tmpComicId
|
||||
// map["dir"] = cacheDir
|
||||
// }))
|
||||
// try {
|
||||
// FileInputStream(path).copyTo(os)
|
||||
// } finally {
|
||||
// File(path).delete()
|
||||
// }
|
||||
// }
|
||||
// resourceQueue.put("OK")
|
||||
// }
|
||||
// else -> resourceQueue.put(Exception("WTF"))
|
||||
// }
|
||||
// } else {
|
||||
// resourceQueue.put(Exception("NOT OK"))
|
||||
// }
|
||||
// } catch (e: Throwable) {
|
||||
// resourceQueue.put(Exception(e))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ import 'dart:convert';
|
|||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
// EventChannel
|
||||
// 由于Flutter的EventChannel只能订阅一次, 且为了和golang的的通信, 这里实现了多次订阅的分发和平铺
|
||||
// 根据eventName订阅和取消订阅
|
||||
|
||||
var _eventChannel = EventChannel("flatEvent");
|
||||
StreamSubscription? _eventChannelListen;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
|||
|
||||
import 'config/TimeOffsetHour.dart';
|
||||
|
||||
/// 默认的图片尺寸
|
||||
double coverWidth = 210;
|
||||
double coverHeight = 315;
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ Future<dynamic> saveImage(String path, BuildContext context) async {
|
|||
}
|
||||
}
|
||||
|
||||
/// 保存图片且保持静默, 用于批量导出到相册
|
||||
Future<dynamic> saveImageQuiet(String path, BuildContext context) async {
|
||||
if (Platform.isIOS) {
|
||||
return method.iosSaveFileToImage(path);
|
||||
|
@ -98,6 +99,7 @@ Future<String?> chooseFolder(BuildContext context) async {
|
|||
);
|
||||
}
|
||||
|
||||
/// 复制对话框
|
||||
void confirmCopy(BuildContext context, String content) async {
|
||||
if (await confirmDialog(context, "复制", content)) {
|
||||
copyToClipBoard(context, content);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// 图片
|
||||
class PicaImage {
|
||||
late String originalName;
|
||||
late String path;
|
||||
|
@ -10,6 +11,7 @@ class PicaImage {
|
|||
}
|
||||
}
|
||||
|
||||
/// 用户基本信息
|
||||
class BasicUser {
|
||||
late String id;
|
||||
late String gender;
|
||||
|
@ -34,6 +36,7 @@ class BasicUser {
|
|||
}
|
||||
}
|
||||
|
||||
/// 用户自己的信息
|
||||
class UserProfile extends BasicUser {
|
||||
late String birthday;
|
||||
late String email;
|
||||
|
@ -48,6 +51,7 @@ class UserProfile extends BasicUser {
|
|||
}
|
||||
}
|
||||
|
||||
/// 分页
|
||||
class Page {
|
||||
late int total;
|
||||
late int limit;
|
||||
|
@ -62,6 +66,7 @@ class Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 分类
|
||||
class Category {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -82,6 +87,7 @@ class Category {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画分页
|
||||
class ComicsPage extends Page {
|
||||
late List<ComicSimple> docs;
|
||||
|
||||
|
@ -93,6 +99,7 @@ class ComicsPage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画基本信息
|
||||
class ComicSimple {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -117,6 +124,7 @@ class ComicSimple {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画详情
|
||||
class ComicInfo extends ComicSimple {
|
||||
late String description;
|
||||
late String chineseTeam;
|
||||
|
@ -145,6 +153,7 @@ class ComicInfo extends ComicSimple {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画创建人信息
|
||||
class Creator extends BasicUser {
|
||||
late String slogan;
|
||||
late String role;
|
||||
|
@ -157,6 +166,7 @@ class Creator extends BasicUser {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画章节
|
||||
class Ep {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -171,6 +181,7 @@ class Ep {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画章节分页
|
||||
class EpPage extends Page {
|
||||
late List<Ep> docs;
|
||||
|
||||
|
@ -182,6 +193,7 @@ class EpPage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画图片分页
|
||||
class PicturePage extends Page {
|
||||
late List<Picture> docs;
|
||||
|
||||
|
@ -193,6 +205,7 @@ class PicturePage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画图片信息
|
||||
class Picture {
|
||||
late String id;
|
||||
late PicaImage media;
|
||||
|
@ -203,6 +216,7 @@ class Picture {
|
|||
}
|
||||
}
|
||||
|
||||
/// 显示图片数据
|
||||
class RemoteImageData {
|
||||
late int fileSize;
|
||||
late String format;
|
||||
|
@ -227,6 +241,7 @@ class RemoteImageData {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画评论分页
|
||||
class CommentPage extends Page {
|
||||
late List<Comment> docs;
|
||||
|
||||
|
@ -238,6 +253,7 @@ class CommentPage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 漫画评论详情
|
||||
class Comment {
|
||||
late String id;
|
||||
late String content;
|
||||
|
@ -264,6 +280,7 @@ class Comment {
|
|||
}
|
||||
}
|
||||
|
||||
/// 评论的用户信息
|
||||
class CommentUser extends BasicUser {
|
||||
late String role;
|
||||
|
||||
|
@ -272,6 +289,7 @@ class CommentUser extends BasicUser {
|
|||
}
|
||||
}
|
||||
|
||||
/// 已下载图片的信息
|
||||
class DownloadPicture {
|
||||
late int rankInEp;
|
||||
late String fileServer;
|
||||
|
@ -294,6 +312,7 @@ class DownloadPicture {
|
|||
}
|
||||
}
|
||||
|
||||
/// 浏览历史记录
|
||||
class ViewLog {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -334,6 +353,7 @@ class ViewLog {
|
|||
}
|
||||
}
|
||||
|
||||
/// 已下载漫画的信息
|
||||
class DownloadComic {
|
||||
late String id;
|
||||
late String createdAt;
|
||||
|
@ -417,6 +437,7 @@ class DownloadComic {
|
|||
}
|
||||
}
|
||||
|
||||
/// 已下载的章节信息
|
||||
class DownloadEp {
|
||||
late String comicId;
|
||||
late String id;
|
||||
|
@ -447,6 +468,7 @@ class DownloadEp {
|
|||
}
|
||||
}
|
||||
|
||||
/// 游戏的分页
|
||||
class GamePage extends Page {
|
||||
late List<GameSimple> docs;
|
||||
|
||||
|
@ -458,6 +480,7 @@ class GamePage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 游戏的简要信息
|
||||
class GameSimple {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -484,6 +507,7 @@ class GameSimple {
|
|||
}
|
||||
}
|
||||
|
||||
/// 游戏详情
|
||||
class GameInfo extends GameSimple {
|
||||
late String description;
|
||||
late String updateContent;
|
||||
|
@ -519,6 +543,7 @@ class GameInfo extends GameSimple {
|
|||
}
|
||||
}
|
||||
|
||||
/// 我的评论页面分页
|
||||
class MyCommentsPage extends Page {
|
||||
late List<MyComment> docs;
|
||||
|
||||
|
@ -528,6 +553,7 @@ class MyCommentsPage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 我的评论
|
||||
class MyComment {
|
||||
late String id;
|
||||
late String content;
|
||||
|
@ -550,6 +576,7 @@ class MyComment {
|
|||
}
|
||||
}
|
||||
|
||||
/// 我的评论漫画简要信息
|
||||
class MyCommentComic {
|
||||
late String id;
|
||||
late String title;
|
||||
|
@ -560,6 +587,7 @@ class MyCommentComic {
|
|||
}
|
||||
}
|
||||
|
||||
/// 子评论分页
|
||||
class CommentChildrenPage extends Page {
|
||||
late List<CommentChild> docs;
|
||||
|
||||
|
@ -573,6 +601,7 @@ class CommentChildrenPage extends Page {
|
|||
}
|
||||
}
|
||||
|
||||
/// 子评论
|
||||
class CommentChild extends Comment {
|
||||
late String parent;
|
||||
|
||||
|
|
|
@ -4,13 +4,18 @@ import 'package:flutter/services.dart';
|
|||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/config/Quality.dart';
|
||||
|
||||
/// 使用MethodChannel与平台通信
|
||||
|
||||
final method = Method._();
|
||||
|
||||
class Method {
|
||||
/// 禁止其他页面构造此类
|
||||
Method._();
|
||||
|
||||
/// channel
|
||||
MethodChannel _channel = MethodChannel("method");
|
||||
|
||||
/// 平铺调用, 为了直接与golang进行通信
|
||||
Future<dynamic> _flatInvoke(String method, dynamic params) {
|
||||
return _channel.invokeMethod("flatInvoke", {
|
||||
"method": method,
|
||||
|
@ -18,20 +23,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
Future<String> loadTheme() async {
|
||||
return await _flatInvoke("loadProperty", {
|
||||
"name": "theme",
|
||||
"defaultValue": "pink",
|
||||
});
|
||||
}
|
||||
|
||||
Future<dynamic> saveTheme(String code) async {
|
||||
return await _flatInvoke("saveProperty", {
|
||||
"name": "theme",
|
||||
"value": code,
|
||||
});
|
||||
}
|
||||
|
||||
/// 读取配置文件
|
||||
Future<String> loadProperty(String propertyName, String defaultValue) async {
|
||||
return await _flatInvoke("loadProperty", {
|
||||
"name": propertyName,
|
||||
|
@ -39,6 +31,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 保存配置文件
|
||||
Future<dynamic> saveProperty(String propertyName, String value) {
|
||||
return _flatInvoke("saveProperty", {
|
||||
"name": propertyName,
|
||||
|
@ -46,61 +39,59 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
Future<String> loadQuality() async {
|
||||
return await _flatInvoke("loadProperty", {
|
||||
"name": "quality",
|
||||
"defaultValue": ImageQualityOriginal,
|
||||
});
|
||||
}
|
||||
|
||||
Future<dynamic> saveQuality(String code) async {
|
||||
return await _flatInvoke("saveProperty", {
|
||||
"name": "quality",
|
||||
"value": code,
|
||||
});
|
||||
}
|
||||
|
||||
/// 获取当前的分流
|
||||
Future<String> getSwitchAddress() async {
|
||||
return await _flatInvoke("getSwitchAddress", "");
|
||||
}
|
||||
|
||||
/// 更换分流
|
||||
Future<dynamic> setSwitchAddress(String switchAddress) async {
|
||||
return await _flatInvoke("setSwitchAddress", switchAddress);
|
||||
}
|
||||
|
||||
/// 获取代理
|
||||
Future<String> getProxy() async {
|
||||
return await _flatInvoke("getProxy", "");
|
||||
}
|
||||
|
||||
/// 更换当前的代理
|
||||
Future<dynamic> setProxy(String proxy) async {
|
||||
return await _flatInvoke("setProxy", proxy);
|
||||
}
|
||||
|
||||
/// 获取用户名
|
||||
Future<String> getUsername() async {
|
||||
return await _flatInvoke("getUsername", "");
|
||||
}
|
||||
|
||||
/// 设置用户名
|
||||
Future<dynamic> setUsername(String username) async {
|
||||
return await _flatInvoke("setUsername", username);
|
||||
}
|
||||
|
||||
/// 获取密码
|
||||
Future<String> getPassword() async {
|
||||
return await _flatInvoke("getPassword", "");
|
||||
}
|
||||
|
||||
/// 设置密码
|
||||
Future<dynamic> setPassword(String password) async {
|
||||
return await _flatInvoke("setPassword", password);
|
||||
}
|
||||
|
||||
/// 预登录, 程序启用时会调用
|
||||
/// 如果又账号密码或token, 且登录成功, 将返回true
|
||||
Future<bool> preLogin() async {
|
||||
String rsp = await _flatInvoke("preLogin", "");
|
||||
return rsp == "true";
|
||||
}
|
||||
|
||||
/// 登录
|
||||
Future<dynamic> login() async {
|
||||
return _flatInvoke("login", "");
|
||||
}
|
||||
|
||||
/// 注册
|
||||
Future<dynamic> register(
|
||||
String email,
|
||||
String name,
|
||||
|
@ -128,19 +119,24 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 退出登录
|
||||
Future<dynamic> clearToken() {
|
||||
return _flatInvoke("clearToken", "");
|
||||
}
|
||||
|
||||
/// 获取用户自身基础信息
|
||||
Future<UserProfile> userProfile() async {
|
||||
String rsp = await _flatInvoke("userProfile", "");
|
||||
return UserProfile.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 打卡
|
||||
Future<dynamic> punchIn() {
|
||||
return _flatInvoke("punchIn", "");
|
||||
}
|
||||
|
||||
/// 使用服务器地址以及路径获取图片用户显示
|
||||
/// 如果本地有缓存会返回路径, 如果本地没有缓存会下载再返回路径, 没有下载成功则会抛出异常
|
||||
Future<RemoteImageData> remoteImageData(
|
||||
String fileServer, String path) async {
|
||||
var data = await _flatInvoke("remoteImageData", {
|
||||
|
@ -150,6 +146,7 @@ class Method {
|
|||
return RemoteImageData.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
/// 功能同上, 用于预加载
|
||||
Future<dynamic> remoteImagePreload(String fileServer, String path) async {
|
||||
return _flatInvoke("remoteImagePreload", {
|
||||
"fileServer": fileServer,
|
||||
|
@ -157,16 +154,26 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 获取已经下载好图片的保存位置
|
||||
Future<String> downloadImagePath(String path) async {
|
||||
return await _flatInvoke("downloadImagePath", path);
|
||||
}
|
||||
|
||||
/// 获取分类
|
||||
Future<List<Category>> categories() async {
|
||||
String rsp = await _flatInvoke("categories", "");
|
||||
List list = json.decode(rsp);
|
||||
return list.map((e) => Category.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 列出漫画
|
||||
/// [sort] 排序方式
|
||||
/// [page] 页数
|
||||
/// [category] 分类
|
||||
/// [tag] 标签
|
||||
/// [creatorId] 创建人ID
|
||||
/// [chineseTeam] 汉化组名称
|
||||
/// * 几种条件使用且的关系
|
||||
Future<ComicsPage> comics(
|
||||
String sort,
|
||||
int page, {
|
||||
|
@ -186,10 +193,12 @@ class Method {
|
|||
return ComicsPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 搜索漫画
|
||||
Future<ComicsPage> searchComics(String keyword, String sort, int page) {
|
||||
return searchComicsInCategories(keyword, sort, page, []);
|
||||
}
|
||||
|
||||
/// 搜索漫画, 在多个分类中
|
||||
Future<ComicsPage> searchComicsInCategories(
|
||||
String keyword, String sort, int page, List<String> categories) async {
|
||||
String rsp = await _flatInvoke("searchComics", {
|
||||
|
@ -201,6 +210,7 @@ class Method {
|
|||
return ComicsPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 随机漫画
|
||||
Future<List<ComicSimple>> randomComics() async {
|
||||
String data = await _flatInvoke("randomComics", "");
|
||||
return List.of(jsonDecode(data))
|
||||
|
@ -209,6 +219,8 @@ class Method {
|
|||
.toList();
|
||||
}
|
||||
|
||||
/// 漫画榜单
|
||||
/// [type] 榜单类型 H24 D7 D30
|
||||
Future<List<ComicSimple>> leaderboard(String type) async {
|
||||
String data = await _flatInvoke("leaderboard", type);
|
||||
return List.of(jsonDecode(data))
|
||||
|
@ -217,11 +229,13 @@ class Method {
|
|||
.toList();
|
||||
}
|
||||
|
||||
/// 获取漫画详情
|
||||
Future<ComicInfo> comicInfo(String comicId) async {
|
||||
String rsp = await _flatInvoke("comicInfo", comicId);
|
||||
return ComicInfo.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 分页获取漫画的章节
|
||||
Future<EpPage> comicEpPage(String comicId, int page) async {
|
||||
String rsp = await _flatInvoke("comicEpPage", {
|
||||
"comicId": comicId,
|
||||
|
@ -230,6 +244,7 @@ class Method {
|
|||
return EpPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 分页获取一个章节的图片, 并且需要图片的质量参数
|
||||
Future<PicturePage> comicPicturePageWithQuality(
|
||||
String comicId, int epOrder, int page, String quality) async {
|
||||
String data = await _flatInvoke("comicPicturePageWithQuality", {
|
||||
|
@ -241,14 +256,17 @@ class Method {
|
|||
return PicturePage.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
/// 对漫画进行点赞/取消点赞操作
|
||||
Future<String> switchLike(String comicId) async {
|
||||
return await _flatInvoke("switchLike", comicId);
|
||||
}
|
||||
|
||||
/// 对漫画进行收藏/取消收藏操作
|
||||
Future<String> switchFavourite(String comicId) async {
|
||||
return await _flatInvoke("switchFavourite", comicId);
|
||||
}
|
||||
|
||||
/// 收藏漫画列表
|
||||
Future<ComicsPage> favouriteComics(String sort, int page) async {
|
||||
var rsp = await _flatInvoke("favouriteComics", {
|
||||
"sort": sort,
|
||||
|
@ -257,12 +275,14 @@ class Method {
|
|||
return ComicsPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 看了此漫画的人还看了...(此接口似乎失效了)
|
||||
Future<List<ComicSimple>> recommendation(String comicId) async {
|
||||
String rsp = await _flatInvoke("recommendation", comicId);
|
||||
List list = json.decode(rsp);
|
||||
return list.map((e) => ComicSimple.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 对漫画发送评论
|
||||
Future<dynamic> postComment(String comicId, String content) {
|
||||
return _flatInvoke("postComment", {
|
||||
"comicId": comicId,
|
||||
|
@ -270,6 +290,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 发送子评论
|
||||
Future<dynamic> postChildComment(String commentId, String content) {
|
||||
return _flatInvoke("postChildComment", {
|
||||
"commentId": commentId,
|
||||
|
@ -277,6 +298,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 漫画的评论列表
|
||||
Future<CommentPage> comments(String comicId, int page) async {
|
||||
var rsp = await _flatInvoke("comments", {
|
||||
"comicId": comicId,
|
||||
|
@ -285,6 +307,7 @@ class Method {
|
|||
return CommentPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 拉取子评论
|
||||
Future<CommentChildrenPage> commentChildren(
|
||||
String comicId,
|
||||
String commentId,
|
||||
|
@ -298,13 +321,13 @@ class Method {
|
|||
return CommentChildrenPage.fromJson(json.decode(rsp));
|
||||
}
|
||||
|
||||
/// 我的评论列表
|
||||
Future<MyCommentsPage> myComments(int page) async {
|
||||
String response = await _flatInvoke("myComments", "$page");
|
||||
print("RESPONSE");
|
||||
print(response);
|
||||
return MyCommentsPage.fromJson(jsonDecode(response));
|
||||
}
|
||||
|
||||
/// 浏览记录
|
||||
Future<List<ViewLog>> viewLogPage(int offset, int limit) async {
|
||||
var data = await _flatInvoke("viewLogPage", {
|
||||
"offset": offset,
|
||||
|
@ -314,32 +337,39 @@ class Method {
|
|||
return list.map((e) => ViewLog.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 清除所有的浏览记录
|
||||
Future<dynamic> clearAllViewLog() {
|
||||
return _flatInvoke("clearAllViewLog", "");
|
||||
}
|
||||
|
||||
/// 删除一个漫画的浏览记录
|
||||
Future<dynamic> deleteViewLog(String id) {
|
||||
return _flatInvoke("deleteViewLog", id);
|
||||
}
|
||||
|
||||
/// 游戏列表
|
||||
Future<GamePage> games(int page) async {
|
||||
var data = await _flatInvoke("games", "$page");
|
||||
return GamePage.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
/// 游戏详情
|
||||
Future<GameInfo> game(String gameId) async {
|
||||
var data = await _flatInvoke("game", gameId);
|
||||
return GameInfo.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
/// 清理缓存
|
||||
Future clean() {
|
||||
return _flatInvoke("clean", "");
|
||||
}
|
||||
|
||||
/// 清理[expireSec]秒以前的缓存
|
||||
Future autoClean(String expireSec) {
|
||||
return _flatInvoke("autoClean", expireSec);
|
||||
}
|
||||
|
||||
/// 保存当前浏览器的进度
|
||||
Future storeViewEp(
|
||||
String comicId, int epOrder, String epTitle, int pictureRank) {
|
||||
return _flatInvoke("storeViewEp", {
|
||||
|
@ -350,6 +380,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 加载浏览进度
|
||||
Future<ViewLog?> loadView(String comicId) async {
|
||||
String data = await _flatInvoke("loadView", comicId);
|
||||
if (data == "") {
|
||||
|
@ -358,15 +389,18 @@ class Method {
|
|||
return ViewLog.fromJson(jsonDecode(data));
|
||||
}
|
||||
|
||||
/// 下载是否在后台运行
|
||||
Future<bool> downloadRunning() async {
|
||||
String rsp = await _flatInvoke("downloadRunning", "");
|
||||
return rsp == "true";
|
||||
}
|
||||
|
||||
/// 暂停/继续 下载
|
||||
Future<dynamic> setDownloadRunning(bool status) async {
|
||||
return _flatInvoke("setDownloadRunning", "$status");
|
||||
}
|
||||
|
||||
/// 下载漫画
|
||||
Future<dynamic> createDownload(
|
||||
Map<String, dynamic> comic, List<Map<String, dynamic>> epList) async {
|
||||
return _flatInvoke("createDownload", {
|
||||
|
@ -375,6 +409,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 追加下载的章节
|
||||
Future<dynamic> addDownload(
|
||||
Map<String, dynamic> comic, List<Map<String, dynamic>> epList) async {
|
||||
await _flatInvoke("addDownload", {
|
||||
|
@ -383,6 +418,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 下载详情
|
||||
Future<DownloadComic?> loadDownloadComic(String comicId) async {
|
||||
var data = await _flatInvoke("loadDownloadComic", comicId);
|
||||
// 未找到 且 未异常
|
||||
|
@ -392,6 +428,7 @@ class Method {
|
|||
return DownloadComic.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
/// 所有下载
|
||||
Future<List<DownloadComic>> allDownloads() async {
|
||||
var data = await _flatInvoke("allDownloads", "");
|
||||
data = jsonDecode(data);
|
||||
|
@ -402,26 +439,31 @@ class Method {
|
|||
return list.map((e) => DownloadComic.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 删除一个下载
|
||||
Future<dynamic> deleteDownloadComic(String comicId) async {
|
||||
return _flatInvoke("deleteDownloadComic", comicId);
|
||||
}
|
||||
|
||||
/// 所有下载的EP
|
||||
Future<List<DownloadEp>> downloadEpList(String comicId) async {
|
||||
var data = await _flatInvoke("downloadEpList", comicId);
|
||||
List list = json.decode(data);
|
||||
return list.map((e) => DownloadEp.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 下载漫画这个EP下的图片
|
||||
Future<List<DownloadPicture>> downloadPicturesByEpId(String epId) async {
|
||||
var data = await _flatInvoke("downloadPicturesByEpId", epId);
|
||||
List list = json.decode(data);
|
||||
return list.map((e) => DownloadPicture.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
/// 重置所有下载失败的漫画
|
||||
Future<dynamic> resetFailed() async {
|
||||
return _flatInvoke("resetAllDownloads", "");
|
||||
}
|
||||
|
||||
/// 导出下载的漫画到zip
|
||||
Future<dynamic> exportComicDownload(String comicId, String dir) {
|
||||
return _flatInvoke("exportComicDownload", {
|
||||
"comicId": comicId,
|
||||
|
@ -429,12 +471,7 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
Future<dynamic> exportComicDownloadAndroidQ(String comicId) {
|
||||
return _channel.invokeMethod("exportComicDownloadAndroidQ", {
|
||||
"comicId": comicId,
|
||||
});
|
||||
}
|
||||
|
||||
/// 导出下载的图片到HTML+JPG
|
||||
Future<dynamic> exportComicDownloadToJPG(String comicId, String dir) {
|
||||
return _flatInvoke("exportComicDownloadToJPG", {
|
||||
"comicId": comicId,
|
||||
|
@ -442,26 +479,32 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
/// 使用网络将下载传输到其他设备
|
||||
Future<int> exportComicUsingSocket(String comicId) async {
|
||||
return int.parse(await _flatInvoke("exportComicUsingSocket", comicId));
|
||||
}
|
||||
|
||||
/// 传输窗口关闭时调用, 令socket关闭(如果传输没有结束)
|
||||
Future<dynamic> exportComicUsingSocketExit() {
|
||||
return _flatInvoke("exportComicUsingSocketExit", "");
|
||||
}
|
||||
|
||||
/// 从zip导入漫画
|
||||
Future<dynamic> importComicDownload(String zipPath) {
|
||||
return _flatInvoke("importComicDownload", zipPath);
|
||||
}
|
||||
|
||||
/// 从网络接收漫画
|
||||
Future<dynamic> importComicDownloadUsingSocket(String addr) {
|
||||
return _flatInvoke("importComicDownloadUsingSocket", addr);
|
||||
}
|
||||
|
||||
/// 获取本机的所有ip地址
|
||||
Future<String> clientIpSet() async {
|
||||
return await _flatInvoke("clientIpSet", "");
|
||||
}
|
||||
|
||||
/// 获取一个游戏的下载地址
|
||||
Future<List<String>> downloadGame(String url) async {
|
||||
if (url.startsWith("https://game.eroge.xyz/hhh.php")) {
|
||||
var data = await _flatInvoke("downloadGame", url);
|
||||
|
@ -470,18 +513,21 @@ class Method {
|
|||
return [url];
|
||||
}
|
||||
|
||||
/// 保存图片(ios)
|
||||
Future<dynamic> iosSaveFileToImage(String path) async {
|
||||
return _channel.invokeMethod("iosSaveFileToImage", {
|
||||
"path": path,
|
||||
});
|
||||
}
|
||||
|
||||
/// 保存图片(android)
|
||||
Future androidSaveFileToImage(String path) async {
|
||||
return _channel.invokeMethod("androidSaveFileToImage", {
|
||||
"path": path,
|
||||
});
|
||||
}
|
||||
|
||||
/// 保存图片(PC)
|
||||
Future convertImageToJPEG100(String path, String dir) async {
|
||||
return _flatInvoke("convertImageToJPEG100", {
|
||||
"path": path,
|
||||
|
@ -489,59 +535,30 @@ class Method {
|
|||
});
|
||||
}
|
||||
|
||||
Future<bool> getAutoFullScreen() async {
|
||||
var value = await _flatInvoke("loadProperty", {
|
||||
"name": "autoFullScreen",
|
||||
"defaultValue": "false",
|
||||
});
|
||||
return value == "true";
|
||||
}
|
||||
|
||||
Future<dynamic> setAutoFullScreen(bool value) async {
|
||||
return await _flatInvoke("saveProperty", {
|
||||
"name": "autoFullScreen",
|
||||
"value": "$value",
|
||||
});
|
||||
}
|
||||
|
||||
Future<List<String>> getShadowCategories() async {
|
||||
var value = await _flatInvoke("loadProperty", {
|
||||
"name": "shadowCategories",
|
||||
"defaultValue": jsonEncode(<String>[]),
|
||||
});
|
||||
return List.of(jsonDecode(value)).map((e) => "$e").toList();
|
||||
}
|
||||
|
||||
Future<dynamic> setShadowCategories(List<String> value) {
|
||||
return _flatInvoke("saveProperty", {
|
||||
"name": "shadowCategories",
|
||||
"value": jsonEncode(value),
|
||||
});
|
||||
}
|
||||
|
||||
/// 获取安卓的屏幕刷新率
|
||||
Future<List<String>> loadAndroidModes() async {
|
||||
return List.of(await _channel.invokeMethod("androidGetModes"))
|
||||
.map((e) => "$e")
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 设置安卓的屏幕刷新率
|
||||
Future setAndroidMode(String androidDisplayMode) {
|
||||
return _channel
|
||||
.invokeMethod("androidSetMode", {"mode": androidDisplayMode});
|
||||
}
|
||||
|
||||
Future androidGetUiMode() {
|
||||
return _channel.invokeMethod("androidGetUiMode", {});
|
||||
}
|
||||
|
||||
/// 获取安卓的版本
|
||||
Future<int> androidGetVersion() async {
|
||||
return await _channel.invokeMethod("androidGetVersion", {});
|
||||
}
|
||||
|
||||
/// 数据文件保存位置
|
||||
Future<String> dataLocal() async {
|
||||
return await _channel.invokeMethod("dataLocal", {});
|
||||
}
|
||||
|
||||
/// 获取安卓支持的文件保存路径
|
||||
Future<List<String>> androidGetExtendDirs() async {
|
||||
String? tmp = await _channel.invokeMethod("androidGetExtendDirs", {});
|
||||
if (tmp != null && tmp.isNotEmpty) {
|
||||
|
@ -550,7 +567,9 @@ class Method {
|
|||
return [];
|
||||
}
|
||||
|
||||
/// 安卓文件迁移
|
||||
Future migrate(String path) async {
|
||||
return _channel.invokeMethod("migrate", {"path": path});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,14 +5,21 @@ import 'package:flutter/material.dart';
|
|||
import '../Common.dart';
|
||||
import '../Method.dart';
|
||||
|
||||
late bool gAutoFullScreen;
|
||||
late bool _autoFullScreen;
|
||||
|
||||
bool currentAutoFullScreen() {
|
||||
return _autoFullScreen;
|
||||
}
|
||||
|
||||
const _propertyName = "autoFullScreen";
|
||||
|
||||
Future<void> initAutoFullScreen() async {
|
||||
gAutoFullScreen = await method.getAutoFullScreen();
|
||||
_autoFullScreen =
|
||||
(await method.loadProperty(_propertyName, "false")) == "true";
|
||||
}
|
||||
|
||||
String autoFullScreenName() {
|
||||
return gAutoFullScreen ? "是" : "否";
|
||||
return _autoFullScreen ? "是" : "否";
|
||||
}
|
||||
|
||||
Future<void> chooseAutoFullScreen(BuildContext context) async {
|
||||
|
@ -20,7 +27,7 @@ Future<void> chooseAutoFullScreen(BuildContext context) async {
|
|||
await chooseListDialog<String>(context, "进入阅读器自动全屏", ["是", "否"]);
|
||||
if (result != null) {
|
||||
var target = result == "是";
|
||||
await method.setAutoFullScreen(target);
|
||||
gAutoFullScreen = target;
|
||||
await method.saveProperty(_propertyName, "$target");
|
||||
_autoFullScreen = target;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,47 @@
|
|||
/// 图片质量
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../Method.dart';
|
||||
|
||||
late String currentQualityCode;
|
||||
|
||||
Future<void> initQuality() async {
|
||||
currentQualityCode = await method.loadQuality();
|
||||
}
|
||||
|
||||
const ImageQualityOriginal = "original";
|
||||
const ImageQualityLow = "low";
|
||||
const ImageQualityMedium = "medium";
|
||||
const _ImageQualityOriginal = "original";
|
||||
const _ImageQualityLow = "low";
|
||||
const _ImageQualityMedium = "medium";
|
||||
const ImageQualityHigh = "high";
|
||||
|
||||
const LabelOriginal = "原图";
|
||||
const LabelLow = "低";
|
||||
const LabelMedium = "中";
|
||||
const LabelHigh = "高";
|
||||
const _LabelOriginal = "原图";
|
||||
const _LabelLow = "低";
|
||||
const _LabelMedium = "中";
|
||||
const _LabelHigh = "高";
|
||||
|
||||
var _qualities = {
|
||||
LabelOriginal: ImageQualityOriginal,
|
||||
LabelLow: ImageQualityLow,
|
||||
LabelMedium: ImageQualityMedium,
|
||||
LabelHigh: ImageQualityHigh,
|
||||
_LabelOriginal: _ImageQualityOriginal,
|
||||
_LabelLow: _ImageQualityLow,
|
||||
_LabelMedium: _ImageQualityMedium,
|
||||
_LabelHigh: ImageQualityHigh,
|
||||
};
|
||||
|
||||
late String _currentQualityCode;
|
||||
|
||||
String currentQualityCode() {
|
||||
return _currentQualityCode;
|
||||
}
|
||||
|
||||
String _currentQualityName() {
|
||||
for (var e in _qualities.entries) {
|
||||
if (e.value == _currentQualityCode) {
|
||||
return e.key;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
const _propertyName = "quality";
|
||||
const _defaultValue = _ImageQualityOriginal;
|
||||
|
||||
Future<void> initQuality() async {
|
||||
_currentQualityCode = await method.loadProperty(_propertyName, _defaultValue);
|
||||
}
|
||||
|
||||
Future<void> chooseQuality(BuildContext context) async {
|
||||
String? code = await showDialog<String>(
|
||||
context: context,
|
||||
|
@ -47,16 +62,22 @@ Future<void> chooseQuality(BuildContext context) async {
|
|||
},
|
||||
);
|
||||
if (code != null) {
|
||||
method.saveQuality(code);
|
||||
currentQualityCode = code;
|
||||
method.saveProperty(_propertyName, code);
|
||||
_currentQualityCode = code;
|
||||
}
|
||||
}
|
||||
|
||||
String currentQualityName() {
|
||||
for (var e in _qualities.entries) {
|
||||
if (e.value == currentQualityCode) {
|
||||
return e.key;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
Widget qualitySetting() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("浏览时的图片质量"),
|
||||
subtitle: Text(_currentQualityName()),
|
||||
onTap: () async {
|
||||
await chooseQuality(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/// 屏蔽的分类
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:event/event.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:multi_select_flutter/dialog/mult_select_dialog.dart';
|
||||
|
@ -9,14 +11,28 @@ import '../Method.dart';
|
|||
import '../store/Categories.dart';
|
||||
|
||||
late List<String> shadowCategories;
|
||||
|
||||
var shadowCategoriesEvent = Event<EventArgs>();
|
||||
|
||||
Future<void> initShadowCategories() async {
|
||||
shadowCategories = await method.getShadowCategories();
|
||||
// mapper
|
||||
|
||||
const _propertyName = "shadowCategories";
|
||||
|
||||
/// 获取封印的类型
|
||||
Future<List<String>> _loadShadowCategories() async {
|
||||
var value = await method.loadProperty(_propertyName, jsonEncode(<String>[]));
|
||||
return List.of(jsonDecode(value)).map((e) => "$e").toList();
|
||||
}
|
||||
|
||||
Future<void> chooseShadowCategories(BuildContext context) async {
|
||||
/// 保存封印的类型
|
||||
Future<dynamic> _saveShadowCategories(List<String> value) {
|
||||
return method.saveProperty(_propertyName, jsonEncode(value));
|
||||
}
|
||||
|
||||
Future<void> initShadowCategories() async {
|
||||
shadowCategories = await _loadShadowCategories();
|
||||
}
|
||||
|
||||
Future<void> _chooseShadowCategories(BuildContext context) async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (ctx) {
|
||||
|
@ -35,7 +51,7 @@ Future<void> chooseShadowCategories(BuildContext context) async {
|
|||
initialValue: initialValue,
|
||||
onConfirm: (List<String>? value) async {
|
||||
if (value != null) {
|
||||
await method.setShadowCategories(value);
|
||||
await _saveShadowCategories(value);
|
||||
shadowCategories = value;
|
||||
shadowCategoriesEvent.broadcast();
|
||||
}
|
||||
|
@ -48,8 +64,23 @@ Future<void> chooseShadowCategories(BuildContext context) async {
|
|||
Widget shadowCategoriesActionButton(BuildContext context) {
|
||||
return IconButton(
|
||||
onPressed: () {
|
||||
chooseShadowCategories(context);
|
||||
_chooseShadowCategories(context);
|
||||
},
|
||||
icon: Icon(Icons.hide_source),
|
||||
);
|
||||
}
|
||||
|
||||
Widget shadowCategoriesSetting() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("封印"),
|
||||
subtitle: Text(jsonEncode(shadowCategories)),
|
||||
onTap: () async {
|
||||
await _chooseShadowCategories(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ import 'package:pikapi/basic/Common.dart';
|
|||
import '../Method.dart';
|
||||
import 'Platform.dart';
|
||||
|
||||
|
||||
// 字体相关
|
||||
|
||||
const _fontFamilyProperty = "fontFamily";
|
||||
|
||||
String? _fontFamily;
|
||||
|
@ -50,6 +53,8 @@ Widget fontSetting() {
|
|||
);
|
||||
}
|
||||
|
||||
// 主题相关
|
||||
|
||||
// 主题包
|
||||
abstract class _ThemePackage {
|
||||
String code();
|
||||
|
@ -168,6 +173,9 @@ final _themePackages = <_ThemePackage>[
|
|||
// 主题更换事件
|
||||
var themeEvent = Event<EventArgs>();
|
||||
|
||||
const _themePropertyName = "theme";
|
||||
const _defaultThemeCode = "pink";
|
||||
|
||||
String? _themeCode;
|
||||
ThemeData? _themeData;
|
||||
ThemeData? _currentDarkTheme;
|
||||
|
@ -217,7 +225,9 @@ const _nightModePropertyName = "androidNightMode";
|
|||
Future<dynamic> initTheme() async {
|
||||
_androidNightMode =
|
||||
await method.loadProperty(_nightModePropertyName, "true") == "true";
|
||||
_changeThemeByCode(await method.loadTheme());
|
||||
_changeThemeByCode(
|
||||
await method.loadProperty(_themePropertyName, _defaultThemeCode),
|
||||
);
|
||||
}
|
||||
|
||||
// 选择主题的对话框
|
||||
|
@ -292,7 +302,7 @@ Future<dynamic> chooseTheme(BuildContext buildContext) async {
|
|||
},
|
||||
);
|
||||
if (theme != null) {
|
||||
method.saveTheme(theme);
|
||||
method.saveProperty(_themePropertyName, theme);
|
||||
_changeThemeByCode(theme);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class ComicReaderScreen extends StatefulWidget {
|
|||
this.initPictureRank,
|
||||
bool? autoFullScreen,
|
||||
}) : super(key: key) {
|
||||
this.autoFullScreen = autoFullScreen ?? gAutoFullScreen;
|
||||
this.autoFullScreen = autoFullScreen ?? currentAutoFullScreen();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -56,7 +56,7 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
|||
widget.comicInfo.id,
|
||||
widget.currentEpOrder,
|
||||
++_needLoadPage,
|
||||
currentQualityCode,
|
||||
currentQualityCode(),
|
||||
);
|
||||
list.addAll(page.docs.map((element) => element.media));
|
||||
} while (page.pages > page.page);
|
||||
|
|
|
@ -29,7 +29,7 @@ class DownloadReaderScreen extends StatefulWidget {
|
|||
this.initPictureRank,
|
||||
bool? autoFullScreen,
|
||||
}) : super(key: key) {
|
||||
this.autoFullScreen = autoFullScreen ?? gAutoFullScreen;
|
||||
this.autoFullScreen = autoFullScreen ?? currentAutoFullScreen();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -38,14 +38,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
Divider(),
|
||||
NetworkSetting(),
|
||||
Divider(),
|
||||
ListTile(
|
||||
title: Text("浏览时的图片质量"),
|
||||
subtitle: Text(currentQualityName()),
|
||||
onTap: () async {
|
||||
await chooseQuality(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
qualitySetting(),
|
||||
ListTile(
|
||||
title: Text("阅读器模式"),
|
||||
subtitle: Text(currentReaderTypeName()),
|
||||
|
@ -81,14 +74,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
volumeControllerSetting(),
|
||||
keyboardControllerSetting(),
|
||||
Divider(),
|
||||
ListTile(
|
||||
title: Text("封印"),
|
||||
subtitle: Text(jsonEncode(shadowCategories)),
|
||||
onTap: () async {
|
||||
await chooseShadowCategories(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
shadowCategoriesSetting(),
|
||||
ListTile(
|
||||
title: Text("列表页加载方式"),
|
||||
subtitle: Text(currentPagerActionName()),
|
||||
|
|
Loading…
Reference in New Issue