mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Feat: Image favorites (#126)
* feat: 增加图片收藏 * feat: 主体图片收藏页面实现 * feat: 点击打开大图浏览 * feat: 数据结构变更 * feat: 基本完成 * feat: 翻译与bug修复 * feat: 实机测试和问题修复 * feat: jm导入, pica历史记录nhentai有问题, 一键反转 * fix: 大小写不一致, 一个htManga, 一个htmanga * feat: 拉取收藏优化 * feat: 改成以ep为准 * feat: 兜底一些可能报错场景 * chore: 没有用到 * feat: 尽量保证和网络收藏顺序一致 * feat: 支持显示热点tag * feat: 支持双击收藏, 不过此时禁止放大图片 * fix: 自动塞封面逻辑完善, 切换快速收藏图片立刻生效 * Refactor * fix updateValue * feat: 双击功能提示 * fix: 被确定取消收藏的才删除 * Refactor ImageFavoritesPage * translate author * feat: 功能提示改到dialog中 * fix text editing * fix text editing * feat: 功能提示放到邮件或长按菜单中 * fix: 修复tag过滤不生效问题 * Improve image loading * The default value of quickCollectImage should be false. * Refactor DragListener * Refactor ImageFavoriteItem & ImageFavoritePhotoView * Refactor * Fix `ImageFavoriteManager.has` * Fix UI * Improve UI --------- Co-authored-by: nyne <me@nyne.dev>
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:venera/foundation/favorites.dart';
|
||||
import 'package:venera/foundation/history.dart';
|
||||
import 'package:venera/foundation/log.dart';
|
||||
import 'package:venera/network/cookie_jar.dart';
|
||||
import 'package:venera/utils/ext.dart';
|
||||
import 'package:zip_flutter/zip_flutter.dart';
|
||||
|
||||
import 'io.dart';
|
||||
@@ -128,7 +129,24 @@ Future<void> importPicaData(File file) async {
|
||||
.select("SELECT name FROM sqlite_master WHERE type='table';")
|
||||
.map((e) => e["name"] as String)
|
||||
.toList();
|
||||
folderNames.removeWhere((e) => e == "folder_order" || e == "folder_sync");
|
||||
folderNames
|
||||
.removeWhere((e) => e == "folder_order" || e == "folder_sync");
|
||||
for (var folderSyncValue in db.select("SELECT * FROM folder_sync;")) {
|
||||
var folderName = folderSyncValue["folder_name"];
|
||||
String sourceKey = folderSyncValue["key"];
|
||||
sourceKey =
|
||||
sourceKey.toLowerCase() == "htmanga" ? "wnacg" : sourceKey;
|
||||
// 有值就跳过
|
||||
if (LocalFavoritesManager().findLinked(folderName).$1 != null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
LocalFavoritesManager().linkFolderToNetwork(folderName, sourceKey,
|
||||
jsonDecode(folderSyncValue["sync_data"])["folderId"]);
|
||||
} catch (e, stack) {
|
||||
Log.error(e.toString(), stack);
|
||||
}
|
||||
}
|
||||
for (var folderName in folderNames) {
|
||||
if (!LocalFavoritesManager().existsFolder(folderName)) {
|
||||
LocalFavoritesManager().createFolder(folderName);
|
||||
@@ -141,7 +159,7 @@ Future<void> importPicaData(File file) async {
|
||||
name: comic['name'],
|
||||
coverPath: comic['cover_path'],
|
||||
author: comic['author'],
|
||||
type: ComicType(switch(comic['type']) {
|
||||
type: ComicType(switch (comic['type']) {
|
||||
0 => 'picacg'.hashCode,
|
||||
1 => 'ehentai'.hashCode,
|
||||
2 => 'jm'.hashCode,
|
||||
@@ -155,11 +173,9 @@ Future<void> importPicaData(File file) async {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
} catch (e) {
|
||||
Log.error("Import Data", "Failed to import local favorite: $e");
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
db.dispose();
|
||||
}
|
||||
}
|
||||
@@ -170,31 +186,80 @@ Future<void> importPicaData(File file) async {
|
||||
for (var comic in db.select("SELECT * FROM history;")) {
|
||||
HistoryManager().addHistory(
|
||||
History.fromMap({
|
||||
"type": switch(comic['type']) {
|
||||
"type": switch (comic['type']) {
|
||||
0 => 'picacg'.hashCode,
|
||||
1 => 'ehentai'.hashCode,
|
||||
2 => 'jm'.hashCode,
|
||||
3 => 'hitomi'.hashCode,
|
||||
4 => 'wnacg'.hashCode,
|
||||
6 => 'nhentai'.hashCode,
|
||||
5 => 'nhentai'.hashCode,
|
||||
_ => comic['type']
|
||||
},
|
||||
"id": comic['target'],
|
||||
"maxPage": comic["max_page"],
|
||||
"max_page": comic["max_page"],
|
||||
"ep": comic["ep"],
|
||||
"page": comic["page"],
|
||||
"time": comic["time"],
|
||||
"title": comic["title"],
|
||||
"subtitle": comic["subtitle"],
|
||||
"cover": comic["cover"],
|
||||
"readEpisode": [comic["ep"]],
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
Log.error("Import Data", "Failed to import history: $e");
|
||||
}
|
||||
finally {
|
||||
List<ImageFavoritesComic> imageFavoritesComicList =
|
||||
ImageFavoriteManager().comics;
|
||||
for (var comic in db.select("SELECT * FROM image_favorites;")) {
|
||||
String sourceKey = comic["id"].split("-")[0];
|
||||
// 换名字了, 绅士漫画
|
||||
if (sourceKey.toLowerCase() == "htmanga") {
|
||||
sourceKey = "wnacg";
|
||||
}
|
||||
if (ComicSource.find(sourceKey) == null) {
|
||||
continue;
|
||||
}
|
||||
String id = comic["id"].split("-")[1];
|
||||
int page = comic["page"];
|
||||
// 章节和page是从1开始的, pica 可能有从 0 开始的, 得转一下
|
||||
int ep = comic["ep"] == 0 ? 1 : comic["ep"];
|
||||
String title = comic["title"];
|
||||
String epName = "";
|
||||
ImageFavoritesComic? tempComic = imageFavoritesComicList
|
||||
.firstWhereOrNull((e) => e.id == id && e.sourceKey == sourceKey);
|
||||
ImageFavorite curImageFavorite =
|
||||
ImageFavorite(page, "", null, "", id, ep, sourceKey, epName);
|
||||
if (tempComic == null) {
|
||||
tempComic = ImageFavoritesComic(id, [], title, sourceKey, [], [],
|
||||
DateTime.now(), "", {}, "", 1);
|
||||
tempComic.imageFavoritesEp = [
|
||||
ImageFavoritesEp("", ep, [curImageFavorite], epName, 1)
|
||||
];
|
||||
imageFavoritesComicList.add(tempComic);
|
||||
} else {
|
||||
ImageFavoritesEp? tempEp =
|
||||
tempComic.imageFavoritesEp.firstWhereOrNull((e) => e.ep == ep);
|
||||
if (tempEp == null) {
|
||||
tempComic.imageFavoritesEp
|
||||
.add(ImageFavoritesEp("", ep, [curImageFavorite], epName, 1));
|
||||
} else {
|
||||
// 如果已经有这个page了, 就不添加了
|
||||
if (tempEp.imageFavorites
|
||||
.firstWhereOrNull((e) => e.page == page) ==
|
||||
null) {
|
||||
tempEp.imageFavorites.add(curImageFavorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var temp in imageFavoritesComicList) {
|
||||
ImageFavoriteManager().addOrUpdateOrDelete(
|
||||
temp,
|
||||
temp == imageFavoritesComicList.last,
|
||||
);
|
||||
}
|
||||
} catch (e, stack) {
|
||||
Log.error("Import Data", "Failed to import history: $e", stack);
|
||||
} finally {
|
||||
db.dispose();
|
||||
}
|
||||
}
|
||||
|
@@ -95,6 +95,8 @@ extension StringExt on String{
|
||||
bool get isURL => _isURL();
|
||||
|
||||
bool get isNum => double.tryParse(this) != null;
|
||||
|
||||
bool get isInt => int.tryParse(this) != null;
|
||||
}
|
||||
|
||||
abstract class ListOrNull{
|
||||
|
@@ -376,7 +376,6 @@ class _IOOverrides extends IOOverrides {
|
||||
return super.createFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
T overrideIO<T>(T Function() f) {
|
||||
|
Reference in New Issue
Block a user