From b390ac9d8f6fed038f1152660fde170d9a0e513f Mon Sep 17 00:00:00 2001 From: FC383 <1030945211@qq.com> Date: Thu, 7 May 2026 21:37:04 +0800 Subject: [PATCH 1/3] Update download.dart --- lib/network/download.dart | 47 ++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/lib/network/download.dart b/lib/network/download.dart index 9b0c96ae1..e73670c26 100644 --- a/lib/network/download.dart +++ b/lib/network/download.dart @@ -558,6 +558,13 @@ extension AddDownloadExt on DownloadManager { DownloadedItem? _getComicFromJson(String id, String json, DateTime time, [String? directory]) { DownloadedItem comic; try { + var decoded = jsonDecode(json); + if (decoded is! Map) { + // JSON 数据损坏,不是预期的 Map 类型 + LogManager.addLog( + LogLevel.error, "IO", "Failed to get a downloaded comic info: json is not a Map"); + return null; + } if (id.contains('-')) { comic = CustomDownloadedItem.fromJson(jsonDecode(json)); } else if (id.startsWith("jm")) { @@ -653,23 +660,31 @@ abstract mixin class _DownloadDb { } /// order: time, title, subtitle, size - List getAll( - [String order = 'time', String direction = 'desc']) { - var result = _db!.select(''' - select * from download - order by $order $direction - '''); - return result - .map( - (e) => _getComicFromJson( - e['id'], - e['json'], - DateTime.fromMillisecondsSinceEpoch(e['time']), - e['directory'] - )!, - ) - .toList(); +List getAll( + [String order = 'time', String direction = 'desc']) { + var result = _db!.select(''' + select * from download + order by $order $direction + '''); + var list = []; + for (var e in result) { + var item = _getComicFromJson( + e['id'], + e['json'], + DateTime.fromMillisecondsSinceEpoch(e['time']), + e['directory'] + ); + if (item != null) { + list.add(item); + } else { + // 自动清理数据库中损坏的记录,不至于一条损坏,全部都读取不了.而且还可以自动修复 + LogManager.addLog( + LogLevel.error, "IO", "Removing corrupted download record: ${e['id']}"); + _deleteFromDb(e['id'] as String); + } } + return list; +} static final _cache = {}; From c0cc10c9001180b6747cba59b0c251ff5ae4b0d2 Mon Sep 17 00:00:00 2001 From: FC383 <1030945211@qq.com> Date: Thu, 7 May 2026 22:11:50 +0800 Subject: [PATCH 2/3] Update download.dart --- lib/network/download.dart | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/network/download.dart b/lib/network/download.dart index e73670c26..8cb39ff60 100644 --- a/lib/network/download.dart +++ b/lib/network/download.dart @@ -668,24 +668,37 @@ List getAll( '''); var list = []; for (var e in result) { - var item = _getComicFromJson( - e['id'], - e['json'], - DateTime.fromMillisecondsSinceEpoch(e['time']), - e['directory'] - ); - if (item != null) { - list.add(item); - } else { - // 自动清理数据库中损坏的记录,不至于一条损坏,全部都读取不了.而且还可以自动修复 - LogManager.addLog( - LogLevel.error, "IO", "Removing corrupted download record: ${e['id']}"); - _deleteFromDb(e['id'] as String); + String? id; + try { + id = e['id'] as String; + var item = _getComicFromJson( + id, + e['json'] as String, + DateTime.fromMillisecondsSinceEpoch(e['time'] as int), + e['directory'] is String ? e['directory'] as String : null, + ); + if (item != null) { + list.add(item); + } else { + _safeDelete(id); + } + } catch (_) { + if (id != null) { + _safeDelete(id); + } } } return list; } +void _safeDelete(String id) { + try { + _deleteFromDb(id); + } catch (e) { + LogManager.addLog(LogLevel.error, "IO", "Failed to remove download record: $e"); + } +} + static final _cache = {}; String getDirectory(String id) { From dd779251fc738a60cfa932ea1ce01bdf2d5f8406 Mon Sep 17 00:00:00 2001 From: FC383 <229264094+FC383@users.noreply.github.com> Date: Thu, 21 May 2026 23:19:14 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=8D=9F=E5=9D=8F?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E8=AE=B0=E5=BD=95=E6=97=B6=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=AE=8B=E7=95=99=E7=A3=81=E7=9B=98=E7=9B=AE?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 fix #254 的遗留问题:getAll 检测到 JSON 损坏记录后仅调用 _safeDelete 删除 DB 行,磁盘上的漫画目录(含 cover.jpg 及图片文件) 成为孤儿文件永久残留。 新增 _tryCleanDisk 辅助方法,在 _safeDelete 前清理对应磁盘目录。 磁盘清理失败不影响 DB 删除,目录不存在时跳过。 --- lib/network/download.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/network/download.dart b/lib/network/download.dart index 8cb39ff60..33d00228f 100644 --- a/lib/network/download.dart +++ b/lib/network/download.dart @@ -680,9 +680,11 @@ List getAll( if (item != null) { list.add(item); } else { + _tryCleanDisk(e['directory']); _safeDelete(id); } } catch (_) { + _tryCleanDisk(e['directory']); if (id != null) { _safeDelete(id); } @@ -698,7 +700,13 @@ void _safeDelete(String id) { LogManager.addLog(LogLevel.error, "IO", "Failed to remove download record: $e"); } } - +void _tryCleanDisk(dynamic directory) { + if (directory is! String || directory.isEmpty) return; + try { + final d = Directory("${DownloadManager().path}/$directory"); + if (d.existsSync()) d.deleteSync(recursive: true); + } catch (_) {} +} static final _cache = {}; String getDirectory(String id) {