mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
更改安卓端的文件访问方式,优化导入逻辑 (#64)
* Refactor import function & Allow import local comics without copying them to local path. * android: use file_picker instead, support directory access for android 10 * Improve import logic * Fix sql query. * Add ability to remove invalid favorite items. * Perform sort before choosing cover * Revert changes of "use file_picker instead". * Try catch on "check update" * Added module 'flutter_saf' * gitignore * remove unsupported arch in build.gradle * Use flutter_saf to handle android's directory and files, improve import logic. * revert changes of 'requestLegacyExternalStorage' * fix cbz import * openDirectoryPlatform * Remove double check on source folder * use openFilePlatform * remove unused import * improve local comic's path handling * bump version * fix pubspec format * return null when comic folder is empty
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sliver_tools/sliver_tools.dart';
|
||||
import 'package:venera/components/components.dart';
|
||||
@@ -497,6 +496,10 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
|
||||
|
||||
String? selectedFolder;
|
||||
|
||||
bool copyToLocalFolder = true;
|
||||
|
||||
bool cancelled = false;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
loading = false;
|
||||
@@ -530,22 +533,23 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
key: key,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 600),
|
||||
...List.generate(importMethods.length, (index) {
|
||||
return RadioListTile(
|
||||
title: Text(importMethods[index]),
|
||||
value: index,
|
||||
groupValue: type,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
type = value as int;
|
||||
});
|
||||
},
|
||||
);
|
||||
}),
|
||||
key: key,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 600),
|
||||
...List.generate(importMethods.length, (index) {
|
||||
return RadioListTile(
|
||||
title: Text(importMethods[index]),
|
||||
value: index,
|
||||
groupValue: type,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
type = value as int;
|
||||
});
|
||||
},
|
||||
);
|
||||
}),
|
||||
if(type != 3)
|
||||
ListTile(
|
||||
title: Text("Add to favorites".tl),
|
||||
trailing: Select(
|
||||
@@ -559,10 +563,19 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
|
||||
},
|
||||
),
|
||||
).paddingHorizontal(8),
|
||||
const SizedBox(height: 8),
|
||||
Text(info).paddingHorizontal(24),
|
||||
],
|
||||
),
|
||||
CheckboxListTile(
|
||||
enabled: true,
|
||||
title: Text("Copy to app local path".tl),
|
||||
value: copyToLocalFolder,
|
||||
onChanged:(v) {
|
||||
setState(() {
|
||||
copyToLocalFolder = !copyToLocalFolder;
|
||||
});
|
||||
}).paddingHorizontal(8),
|
||||
const SizedBox(height: 8),
|
||||
Text(info).paddingHorizontal(24),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Button.text(
|
||||
child: Row(
|
||||
@@ -620,18 +633,20 @@ class _ImportComicsWidgetState extends State<_ImportComicsWidget> {
|
||||
|
||||
void selectAndImport() async {
|
||||
height = key.currentContext!.size!.height;
|
||||
|
||||
setState(() {
|
||||
loading = true;
|
||||
});
|
||||
var importer = ImportComic(selectedFolder: selectedFolder);
|
||||
var result = false;
|
||||
if (type == 2) {
|
||||
result = await importer.cbz();
|
||||
} else if (type == 3) {
|
||||
result = await importer.ehViewer();
|
||||
} else {
|
||||
result = await importer.directory(type == 0);
|
||||
}
|
||||
var importer = ImportComic(
|
||||
selectedFolder: selectedFolder,
|
||||
copyToLocal: copyToLocalFolder);
|
||||
var result = switch(type) {
|
||||
0 => await importer.directory(true),
|
||||
1 => await importer.directory(false),
|
||||
2 => await importer.cbz(),
|
||||
3 => await importer.ehViewer(),
|
||||
int() => true,
|
||||
};
|
||||
if(result) {
|
||||
context.pop();
|
||||
} else {
|
||||
|
@@ -604,7 +604,7 @@ ImageProvider _createImageProvider(int page, BuildContext context) {
|
||||
var reader = context.reader;
|
||||
var imageKey = reader.images![page - 1];
|
||||
if (imageKey.startsWith('file://')) {
|
||||
return FileImage(File(imageKey.replaceFirst("file://", '')));
|
||||
return FileImage(openFilePlatform(imageKey.replaceFirst("file://", '')));
|
||||
} else {
|
||||
return ReaderImageProvider(
|
||||
imageKey,
|
||||
|
@@ -469,7 +469,7 @@ class _ReaderScaffoldState extends State<_ReaderScaffold> {
|
||||
ImageProvider image;
|
||||
var imageKey = images[index];
|
||||
if (imageKey.startsWith('file://')) {
|
||||
image = FileImage(File(imageKey.replaceFirst("file://", '')));
|
||||
image = FileImage(openFilePlatform(imageKey.replaceFirst("file://", '')));
|
||||
} else {
|
||||
image = ReaderImageProvider(
|
||||
imageKey,
|
||||
@@ -515,7 +515,7 @@ class _ReaderScaffoldState extends State<_ReaderScaffold> {
|
||||
}
|
||||
}
|
||||
if (imageKey.startsWith("file://")) {
|
||||
return await File(imageKey.substring(7)).readAsBytes();
|
||||
return await openFilePlatform(imageKey.substring(7)).readAsBytes();
|
||||
} else {
|
||||
return (await CacheManager().findCache(
|
||||
"$imageKey@${context.reader.type.sourceKey}@${context.reader.cid}@${context.reader.eid}"))!
|
||||
|
@@ -86,29 +86,33 @@ Future<bool> checkUpdate() async {
|
||||
}
|
||||
|
||||
Future<void> checkUpdateUi([bool showMessageIfNoUpdate = true]) async {
|
||||
var value = await checkUpdate();
|
||||
if (value) {
|
||||
showDialog(
|
||||
context: App.rootContext,
|
||||
builder: (context) {
|
||||
return ContentDialog(
|
||||
title: "New version available".tl,
|
||||
content: Text(
|
||||
"A new version is available. Do you want to update now?".tl),
|
||||
actions: [
|
||||
Button.text(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
launchUrlString(
|
||||
"https://github.com/venera-app/venera/releases");
|
||||
},
|
||||
child: Text("Update".tl),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
} else if (showMessageIfNoUpdate) {
|
||||
App.rootContext.showMessage(message: "No new version available".tl);
|
||||
try {
|
||||
var value = await checkUpdate();
|
||||
if (value) {
|
||||
showDialog(
|
||||
context: App.rootContext,
|
||||
builder: (context) {
|
||||
return ContentDialog(
|
||||
title: "New version available".tl,
|
||||
content: Text(
|
||||
"A new version is available. Do you want to update now?".tl),
|
||||
actions: [
|
||||
Button.text(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
launchUrlString(
|
||||
"https://github.com/venera-app/venera/releases");
|
||||
},
|
||||
child: Text("Update".tl),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
} else if (showMessageIfNoUpdate) {
|
||||
App.rootContext.showMessage(message: "No new version available".tl);
|
||||
}
|
||||
} catch (e, s) {
|
||||
Log.error("Check Update", e.toString(), s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,16 @@ class _LocalFavoritesSettingsState extends State<LocalFavoritesSettings> {
|
||||
for (var e in LocalFavoritesManager().folderNames) e: e
|
||||
},
|
||||
).toSliver(),
|
||||
_CallbackSetting(
|
||||
title: "Delete all unavailable local favorite items".tl,
|
||||
callback: () async {
|
||||
var controller = showLoadingDialog(context);
|
||||
var count = await LocalFavoritesManager().removeInvalid();
|
||||
controller.close();
|
||||
context.showMessage(message: "Deleted @a favorite items".tlParams({'a': count}));
|
||||
},
|
||||
actionTitle: 'Delete'.tl,
|
||||
).toSliver(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user