Local Comic: Add "Open Folder" button (#443)

This commit is contained in:
Selene29
2025-07-13 12:52:23 +02:00
committed by GitHub
parent 0b9de68c86
commit 951bcae603
2 changed files with 61 additions and 0 deletions

View File

@@ -398,6 +398,7 @@
"Clear Unfavorited": "清除未收藏", "Clear Unfavorited": "清除未收藏",
"Reverse": "反转", "Reverse": "反转",
"Delete Chapters": "删除章节", "Delete Chapters": "删除章节",
"Open Folder": "打开文件夹",
"Path copied to clipboard": "路径已复制到剪贴板", "Path copied to clipboard": "路径已复制到剪贴板",
"Reverse default chapter order": "反转默认章节顺序" "Reverse default chapter order": "反转默认章节顺序"
}, },
@@ -800,6 +801,7 @@
"Clear Unfavorited": "清除未收藏", "Clear Unfavorited": "清除未收藏",
"Reverse": "反轉", "Reverse": "反轉",
"Delete Chapters": "刪除章節", "Delete Chapters": "刪除章節",
"Open Folder": "打開資料夾",
"Path copied to clipboard": "路徑已複製到剪貼簿", "Path copied to clipboard": "路徑已複製到剪貼簿",
"Reverse default chapter order": "反轉預設章節順序" "Reverse default chapter order": "反轉預設章節順序"
} }

View File

@@ -14,6 +14,7 @@ import 'package:venera/utils/io.dart';
import 'package:venera/utils/pdf.dart'; import 'package:venera/utils/pdf.dart';
import 'package:venera/utils/translations.dart'; import 'package:venera/utils/translations.dart';
import 'package:zip_flutter/zip_flutter.dart'; import 'package:zip_flutter/zip_flutter.dart';
import 'package:url_launcher/url_launcher_string.dart';
class LocalComicsPage extends StatefulWidget { class LocalComicsPage extends StatefulWidget {
const LocalComicsPage({super.key}); const LocalComicsPage({super.key});
@@ -143,6 +144,14 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
addFavorite(selectedComics.keys.toList()); addFavorite(selectedComics.keys.toList());
}, },
), ),
if (selectedComics.length == 1)
MenuEntry(
icon: Icons.folder_open,
text: "Open Folder".tl,
onClick: () {
openComicFolder(selectedComics.keys.first);
},
),
if (selectedComics.length == 1) if (selectedComics.length == 1)
MenuEntry( MenuEntry(
icon: Icons.chrome_reader_mode_outlined, icon: Icons.chrome_reader_mode_outlined,
@@ -313,6 +322,13 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
}, },
menuBuilder: (c) { menuBuilder: (c) {
return [ return [
MenuEntry(
icon: Icons.folder_open,
text: "Open Folder".tl,
onClick: () {
openComicFolder(c as LocalComic);
},
),
MenuEntry( MenuEntry(
icon: Icons.delete, icon: Icons.delete,
text: "Delete".tl, text: "Delete".tl,
@@ -519,6 +535,49 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
typedef ExportComicFunc = Future<File> Function( typedef ExportComicFunc = Future<File> Function(
LocalComic comic, String outFilePath); LocalComic comic, String outFilePath);
/// Opens the folder containing the comic in the system file explorer
Future<void> openComicFolder(LocalComic comic) async {
try {
final folderPath = comic.baseDir;
if (App.isWindows) {
await Process.run('explorer', [folderPath]);
} else if (App.isMacOS) {
await Process.run('open', [folderPath]);
} else if (App.isLinux) {
// Try different file managers commonly found on Linux
try {
await Process.run('xdg-open', [folderPath]);
} catch (e) {
// Fallback to other common file managers
try {
await Process.run('nautilus', [folderPath]);
} catch (e) {
try {
await Process.run('dolphin', [folderPath]);
} catch (e) {
try {
await Process.run('thunar', [folderPath]);
} catch (e) {
// Last resort: use the URL launcher with file:// protocol
await launchUrlString('file://$folderPath');
}
}
}
}
} else {
// For mobile platforms, use the URL launcher with file:// protocol
await launchUrlString('file://$folderPath');
}
} catch (e, s) {
Log.error("Open Folder", "Failed to open comic folder: $e", s);
// Show error message to user
if (App.rootContext.mounted) {
App.rootContext.showMessage(message: "Failed to open folder: $e");
}
}
}
void showDeleteChaptersPopWindow(BuildContext context, LocalComic comic) { void showDeleteChaptersPopWindow(BuildContext context, LocalComic comic) {
var chapters = <String>[]; var chapters = <String>[];