This commit is contained in:
kunfei
2023-03-14 10:18:39 +08:00
parent 75af172b0a
commit f44e73a974
6 changed files with 80 additions and 70 deletions
@@ -49,6 +49,7 @@ import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.File
class BookInfoActivity : class BookInfoActivity :
VMBaseActivity<ActivityBookInfoBinding, BookInfoViewModel>(toolBarTheme = Theme.Dark), VMBaseActivity<ActivityBookInfoBinding, BookInfoViewModel>(toolBarTheme = Theme.Dark),
@@ -559,18 +560,18 @@ class BookInfoActivity :
} }
private fun showDecompressFileImportAlert( private fun showDecompressFileImportAlert(
fileDocs: List<FileDoc> files: List<File>
) { ) {
if (fileDocs.isEmpty()) { if (files.isEmpty()) {
toastOnUi(R.string.unsupport_archivefile_entry) toastOnUi(R.string.unsupport_archivefile_entry)
return return
} }
val selectorNames = fileDocs.map { it.name } val selectorNames = files.map { it.name }
selector( selector(
R.string.import_select_book, R.string.import_select_book,
selectorNames selectorNames
) { _, _, index -> ) { _, _, index ->
viewModel.importBook(fileDocs[index]) viewModel.importBook(files[index])
} }
} }
@@ -28,6 +28,8 @@ import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import java.io.File
import java.io.FileInputStream
class BookInfoViewModel(application: Application) : BaseViewModel(application) { class BookInfoViewModel(application: Application) : BaseViewModel(application) {
val bookData = MutableLiveData<Book>() val bookData = MutableLiveData<Book>()
@@ -279,11 +281,11 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
} }
} }
fun deCompress(archiveFileUri: Uri, onSuccess: (List<FileDoc>) -> Unit) { fun deCompress(archiveFileUri: Uri, onSuccess: (List<File>) -> Unit) {
execute { execute {
ArchiveUtils.deCompress(archiveFileUri).list { ArchiveUtils.deCompress(archiveFileUri).filter {
AppPattern.bookFileRegex.matches(it.name) AppPattern.bookFileRegex.matches(it.name)
} ?: emptyList() }
}.onError { }.onError {
context.toastOnUi("DeCompress Error:\n${it.localizedMessage}") context.toastOnUi("DeCompress Error:\n${it.localizedMessage}")
}.onSuccess { }.onSuccess {
@@ -291,10 +293,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
} }
} }
fun importBook(fileDoc: FileDoc) { fun importBook(file: File) {
val uri = LocalBook.saveBookFile( val uri = LocalBook.saveBookFile(
fileDoc.uri.inputStream(context).getOrThrow(), FileInputStream(file),
fileDoc.name file.name
) )
changeToLocalBook(LocalBook.importFile(uri)) changeToLocalBook(LocalBook.importFile(uri))
} }
@@ -20,40 +20,40 @@ object ArchiveUtils {
fun deCompress( fun deCompress(
archiveUri: Uri, archiveUri: Uri,
path: String = TEMP_PATH path: String = TEMP_PATH
): FileDoc { ): List<File> {
return deCompress(FileDoc.fromUri(archiveUri, false), path) return deCompress(FileDoc.fromUri(archiveUri, false), path)
} }
fun deCompress( fun deCompress(
archivePath: String, archivePath: String,
path: String = TEMP_PATH path: String = TEMP_PATH
): FileDoc { ): List<File> {
return deCompress(Uri.parse(archivePath), path) return deCompress(Uri.parse(archivePath), path)
} }
fun deCompress( fun deCompress(
archiveFile: File, archiveFile: File,
path: String = TEMP_PATH path: String = TEMP_PATH
): FileDoc { ): List<File> {
return deCompress(FileDoc.fromFile(archiveFile), path) return deCompress(FileDoc.fromFile(archiveFile), path)
} }
fun deCompress( fun deCompress(
archiveDoc: DocumentFile, archiveDoc: DocumentFile,
path: String = TEMP_PATH path: String = TEMP_PATH
): FileDoc { ): List<File> {
return deCompress(FileDoc.fromDocumentFile(archiveDoc), path) return deCompress(FileDoc.fromDocumentFile(archiveDoc), path)
} }
fun deCompress( fun deCompress(
archiveFileDoc: FileDoc, archiveFileDoc: FileDoc,
path: String = TEMP_PATH path: String = TEMP_PATH
): FileDoc { ): List<File> {
if (archiveFileDoc.isDir) throw IllegalArgumentException("Unexpected Folder input") if (archiveFileDoc.isDir) throw IllegalArgumentException("Unexpected Folder input")
val name = archiveFileDoc.name val name = archiveFileDoc.name
val workPathFileDoc = getCacheFolderFileDoc(name, path) val workPathFileDoc = getCacheFolderFileDoc(name, path)
val workPath = workPathFileDoc.toString() val workPath = workPathFileDoc.toString()
archiveFileDoc.uri.inputStream(appCtx).getOrThrow().use { return archiveFileDoc.uri.inputStream(appCtx).getOrThrow().use {
when { when {
name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath) name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath)
name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath) name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath)
@@ -61,7 +61,6 @@ object ArchiveUtils {
else -> throw IllegalArgumentException("Unexpected archive format") else -> throw IllegalArgumentException("Unexpected archive format")
} }
} }
return workPathFileDoc
} }
private fun getCacheFolderFileDoc( private fun getCacheFolderFileDoc(
@@ -13,57 +13,57 @@ import java.io.InputStream
object RarUtils { object RarUtils {
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(inputStream: InputStream, path: String) { fun unRarToPath(inputStream: InputStream, path: String): List<File> {
unRarToPath(inputStream, File(path)) return unRarToPath(inputStream, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(byteArray: ByteArray, path: String) { fun unRarToPath(byteArray: ByteArray, path: String): List<File> {
unRarToPath(byteArray, File(path)) return unRarToPath(byteArray, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(zipPath: String, path: String) { fun unRarToPath(zipPath: String, path: String): List<File> {
unRarToPath(zipPath, File(path)) return unRarToPath(zipPath, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(file: File, path: String) { fun unRarToPath(file: File, path: String): List<File> {
unRarToPath(file, File(path)) return unRarToPath(file, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(inputStream: InputStream, destDir: File?) { fun unRarToPath(inputStream: InputStream, destDir: File?): List<File> {
Archive(inputStream).use { return Archive(inputStream).use {
unRarToPath(it, destDir)
}
inputStream.close()
}
@Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(byteArray: ByteArray, destDir: File?) {
Archive(ByteArrayInputStream(byteArray)).use {
unRarToPath(it, destDir) unRarToPath(it, destDir)
} }
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(filePath: String, destDir: File?) { fun unRarToPath(byteArray: ByteArray, destDir: File?): List<File> {
Archive(File(filePath)).use { return Archive(ByteArrayInputStream(byteArray)).use {
unRarToPath(it, destDir) unRarToPath(it, destDir)
} }
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(file: File, destDir: File?) { fun unRarToPath(filePath: String, destDir: File?): List<File> {
Archive(file).use { return Archive(File(filePath)).use {
unRarToPath(it, destDir) unRarToPath(it, destDir)
} }
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(archive: Archive, destDir: File?) { fun unRarToPath(file: File, destDir: File?): List<File> {
return Archive(file).use {
unRarToPath(it, destDir)
}
}
@Throws(NullPointerException::class, SecurityException::class)
fun unRarToPath(archive: Archive, destDir: File?): List<File> {
destDir ?: throw NullPointerException("解决路径不能为空") destDir ?: throw NullPointerException("解决路径不能为空")
val files = arrayListOf<File>()
var entry: FileHeader? var entry: FileHeader?
while (archive.nextFileHeader().also { entry = it } != null) { while (archive.nextFileHeader().also { entry = it } != null) {
val entryFile = File(destDir, entry!!.fileName) val entryFile = File(destDir, entry!!.fileName)
@@ -86,8 +86,10 @@ object RarUtils {
} }
FileOutputStream(entryFile).use { FileOutputStream(entryFile).use {
archive.getInputStream(entry).copyTo(it) archive.getInputStream(entry).copyTo(it)
files.add(entryFile)
} }
} }
return files
} }
} }
@@ -17,59 +17,60 @@ import java.nio.channels.FileChannel
object SevenZipUtils { object SevenZipUtils {
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(inputStream: InputStream, path: String) { fun un7zToPath(inputStream: InputStream, path: String): List<File> {
un7zToPath(inputStream, File(path)) return un7zToPath(inputStream, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(byteArray: ByteArray, path: String) { fun un7zToPath(byteArray: ByteArray, path: String): List<File> {
un7zToPath(byteArray, File(path)) return un7zToPath(byteArray, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(pfd: ParcelFileDescriptor, path: String) { fun un7zToPath(pfd: ParcelFileDescriptor, path: String): List<File> {
un7zToPath(pfd, File(path)) return un7zToPath(pfd, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(fileChannel: FileChannel, path: String) { fun un7zToPath(fileChannel: FileChannel, path: String): List<File> {
un7zToPath(fileChannel, File(path)) return un7zToPath(fileChannel, File(path))
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(inputStream: InputStream, destDir: File?) { fun un7zToPath(inputStream: InputStream, destDir: File?): List<File> {
un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir) return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir)
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(byteArray: ByteArray, destDir: File?) { fun un7zToPath(byteArray: ByteArray, destDir: File?): List<File> {
un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir) return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir)
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?) { fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?): List<File> {
un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir) return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir)
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(fileChannel: FileChannel, destDir: File?) { fun un7zToPath(fileChannel: FileChannel, destDir: File?): List<File> {
un7zToPath(SevenZFile(fileChannel), destDir) return un7zToPath(SevenZFile(fileChannel), destDir)
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(file: File, destDir: File?) { fun un7zToPath(file: File, destDir: File?): List<File> {
un7zToPath(SevenZFile(file), destDir) return un7zToPath(SevenZFile(file), destDir)
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(filePath: String, destDir: File?) { fun un7zToPath(filePath: String, destDir: File?): List<File> {
un7zToPath(SevenZFile(File(filePath)), destDir) return un7zToPath(SevenZFile(File(filePath)), destDir)
} }
@Throws(NullPointerException::class, SecurityException::class) @Throws(NullPointerException::class, SecurityException::class)
fun un7zToPath(sevenZFile: SevenZFile, destDir: File?) { fun un7zToPath(sevenZFile: SevenZFile, destDir: File?): List<File> {
destDir ?: throw NullPointerException("解决路径不能为空") destDir ?: throw NullPointerException("解决路径不能为空")
val files = arrayListOf<File>()
var entry: SevenZArchiveEntry? var entry: SevenZArchiveEntry?
while (sevenZFile.nextEntry.also { entry = it } != null) { while (sevenZFile.nextEntry.also { entry = it } != null) {
val entryFile = File(destDir, entry!!.name) val entryFile = File(destDir, entry!!.name)
@@ -92,7 +93,9 @@ object SevenZipUtils {
} }
FileOutputStream(entryFile).use { FileOutputStream(entryFile).use {
sevenZFile.getInputStream(entry).copyTo(it) sevenZFile.getInputStream(entry).copyTo(it)
files.add(entryFile)
} }
} }
return files
} }
} }
@@ -177,35 +177,36 @@ object ZipUtils {
} }
@Throws(SecurityException::class) @Throws(SecurityException::class)
fun unZipToPath(file: File, path: String) { fun unZipToPath(file: File, path: String): List<File> {
FileInputStream(file).use { return FileInputStream(file).use {
unZipToPath(it, path) unZipToPath(it, path)
} }
} }
@Throws(SecurityException::class) @Throws(SecurityException::class)
fun unZipToPath(file: File, dir: File) { fun unZipToPath(file: File, dir: File): List<File> {
FileInputStream(file).use { return FileInputStream(file).use {
unZipToPath(it, dir) unZipToPath(it, dir)
} }
} }
@Throws(SecurityException::class) @Throws(SecurityException::class)
fun unZipToPath(inputStream: InputStream, path: String) { fun unZipToPath(inputStream: InputStream, path: String): List<File> {
ZipInputStream(inputStream).use { return ZipInputStream(inputStream).use {
unZipToPath(it, File(path)) unZipToPath(it, File(path))
} }
} }
@Throws(SecurityException::class) @Throws(SecurityException::class)
fun unZipToPath(inputStream: InputStream, dir: File) { fun unZipToPath(inputStream: InputStream, dir: File): List<File> {
ZipInputStream(inputStream).use { return ZipInputStream(inputStream).use {
unZipToPath(it, dir) unZipToPath(it, dir)
} }
} }
@Throws(SecurityException::class) @Throws(SecurityException::class)
fun unZipToPath(zipInputStream: ZipInputStream, dir: File) { fun unZipToPath(zipInputStream: ZipInputStream, dir: File): List<File> {
val files = arrayListOf<File>()
var entry: ZipEntry? var entry: ZipEntry?
while (zipInputStream.nextEntry.also { entry = it } != null) { while (zipInputStream.nextEntry.also { entry = it } != null) {
val entryFile = File(dir, entry!!.name) val entryFile = File(dir, entry!!.name)
@@ -228,8 +229,10 @@ object ZipUtils {
} }
FileOutputStream(entryFile).use { FileOutputStream(entryFile).use {
zipInputStream.copyTo(it) zipInputStream.copyTo(it)
files.add(entryFile)
} }
} }
return files
} }