diff --git a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt index f706a0c56..df335d8ca 100644 --- a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.net.Uri import android.os.Build import android.os.Bundle -import android.provider.DocumentsContract import android.view.Menu import android.view.MenuItem import androidx.activity.viewModels @@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File -import java.util.* /** * 导入本地书籍界面 @@ -43,7 +41,7 @@ class ImportBookActivity : VMBaseActivity() - + private val bookFileRegex = Regex("(?i).*\\.(txt|epub|umd)") private var rootDoc: DocumentFile? = null private val subDocs = arrayListOf() private val adapter by lazy { ImportBookAdapter(this, this) } @@ -191,17 +189,11 @@ class ImportBookActivity : VMBaseActivity + when { + item.name.startsWith(".") -> false + item.isDir -> true + else -> item.name.matches(bookFileRegex) } } docList.sortWith(compareBy({ !it.isDir }, { it.name })) @@ -217,36 +209,24 @@ class ImportBookActivity : VMBaseActivity() - File(path).listFiles()?.forEach { - if (it.isDirectory) { - if (!it.name.startsWith(".")) - docList.add( - DocItem( - it.name, - DocumentsContract.Document.MIME_TYPE_DIR, - it.length(), - Date(it.lastModified()), - Uri.fromFile(it) - ) - ) - } else if (it.name.endsWith(".txt", true) - || it.name.endsWith(".epub", true) - || it.name.endsWith(".umd", true) - ) { - docList.add( - DocItem( - it.name, - it.extension, - it.length(), - Date(it.lastModified()), - Uri.fromFile(it) - ) - ) + adapter.clearItems() + launch(IO) { + kotlin.runCatching { + val docList = DocumentUtils.listFiles(path) { + when { + it.name.startsWith(".") -> false + it.isDirectory -> true + else -> it.name.matches(bookFileRegex) + } + } + docList.sortWith(compareBy({ !it.isDir }, { it.name })) + withContext(Main) { + adapter.setItems(docList) + } + }.onFailure { + toastOnUi("获取文件列表出错\n${it.localizedMessage}") } } - docList.sortWith(compareBy({ !it.isDir }, { it.name })) - adapter.setItems(docList) } /** @@ -298,7 +278,7 @@ class ImportBookActivity : VMBaseActivity Unit = { + private val find: (docItem: FileDoc) -> Unit = { launch { adapter.addItem(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt index 75364291d..8180f1e7c 100644 --- a/app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt @@ -13,7 +13,7 @@ import io.legado.app.utils.* class ImportBookAdapter(context: Context, val callBack: CallBack) : - RecyclerAdapter(context) { + RecyclerAdapter(context) { var selectedUris = hashSetOf() var checkableCount = 0 private var bookFileNames = arrayListOf() @@ -29,7 +29,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) : override fun convert( holder: ItemViewHolder, binding: ItemImportBookBinding, - item: DocItem, + item: FileDoc, payloads: MutableList ) { binding.run { diff --git a/app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt index 209e3bf3b..e5ffa13da 100644 --- a/app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt @@ -5,8 +5,8 @@ import android.net.Uri import androidx.documentfile.provider.DocumentFile import io.legado.app.base.BaseViewModel import io.legado.app.model.localBook.LocalBook -import io.legado.app.utils.DocItem import io.legado.app.utils.DocumentUtils +import io.legado.app.utils.FileDoc import io.legado.app.utils.isContentScheme import io.legado.app.utils.toastOnUi import java.io.File @@ -45,12 +45,11 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application) fun scanDoc( documentFile: DocumentFile, isRoot: Boolean, - find: (docItem: DocItem) -> Unit, + find: (docItem: FileDoc) -> Unit, finally: (() -> Unit)? = null ) { kotlin.runCatching { - val docList = DocumentUtils.listFiles(documentFile.uri) - docList.forEach { docItem -> + DocumentUtils.listFiles(documentFile.uri).forEach { docItem -> if (docItem.isDir) { DocumentFile.fromSingleUri(context, docItem.uri)?.let { scanDoc(it, false, find) @@ -72,7 +71,7 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application) fun scanFile( file: File, isRoot: Boolean, - find: (docItem: DocItem) -> Unit, + find: (docItem: FileDoc) -> Unit, finally: (() -> Unit)? = null ) { file.listFiles()?.forEach { @@ -82,9 +81,9 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application) || it.name.endsWith(".epub", true) ) { find( - DocItem( + FileDoc( it.name, - it.extension, + it.isDirectory, it.length(), Date(it.lastModified()), Uri.parse(it.absolutePath) diff --git a/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt b/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt index ad526c69e..8f4777220 100644 --- a/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt @@ -13,7 +13,7 @@ import java.io.File import java.net.URLDecoder class FontAdapter(context: Context, curFilePath: String, val callBack: CallBack) : - RecyclerAdapter(context) { + RecyclerAdapter(context) { private val curName = URLDecoder.decode(curFilePath, "utf-8") .substringAfterLast(File.separator) @@ -25,12 +25,12 @@ class FontAdapter(context: Context, curFilePath: String, val callBack: CallBack) override fun convert( holder: ItemViewHolder, binding: ItemFontBinding, - item: DocItem, + item: FileDoc, payloads: MutableList ) { binding.run { kotlin.runCatching { - val typeface: Typeface? = if (item.isContentPath) { + val typeface: Typeface? = if (item.isContentScheme) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.contentResolver .openFileDescriptor(item.uri, "r") @@ -67,6 +67,6 @@ class FontAdapter(context: Context, curFilePath: String, val callBack: CallBack) } interface CallBack { - fun onClick(docItem: DocItem) + fun onClick(docItem: FileDoc) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt b/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt index 0db688205..3a1002d8b 100644 --- a/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt +++ b/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt @@ -126,29 +126,18 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select), } } - private fun getLocalFonts(): ArrayList { - val fontItems = arrayListOf() - val fontDir = - FileUtils.createFolderIfNotExist(requireContext().externalFiles, "font") - fontDir.listFiles { pathName -> - pathName.name.lowercase(Locale.getDefault()).matches(fontRegex) - }?.forEach { - fontItems.add( - DocItem( - it.name, - it.extension, - it.length(), - Date(it.lastModified()), - Uri.parse(it.absolutePath) - ) - ) + private fun getLocalFonts(): ArrayList { + val path = FileUtils.getPath(requireContext().externalFiles, "font") + return DocumentUtils.listFiles(path) { + it.name.matches(fontRegex) } - return fontItems } private fun loadFontFiles(doc: DocumentFile) { execute { - val fontItems = DocumentUtils.listFiles(doc.uri, fontRegex) + val fontItems = DocumentUtils.listFiles(doc.uri) { + it.name.matches(fontRegex) + } mergeFontItems(fontItems, getLocalFonts()) }.onSuccess { adapter.setItems(it) @@ -169,7 +158,9 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select), private fun loadFontFiles(path: String) { execute { - val fontItems = DocumentUtils.listFiles(path, fontRegex) + val fontItems = DocumentUtils.listFiles(path) { + it.name.matches(fontRegex) + } mergeFontItems(fontItems, getLocalFonts()) }.onSuccess { adapter.setItems(it) @@ -179,9 +170,9 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select), } private fun mergeFontItems( - items1: ArrayList, - items2: ArrayList - ): List { + items1: ArrayList, + items2: ArrayList + ): List { val items = ArrayList(items1) items2.forEach { item2 -> var isInFirst = false @@ -200,7 +191,7 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select), } } - override fun onClick(docItem: DocItem) { + override fun onClick(docItem: FileDoc) { execute { FileUtils.deleteFile(fontFolder.absolutePath) callBack?.selectFont(docItem.uri.toString()) diff --git a/app/src/main/java/io/legado/app/utils/DocumentExtensions.kt b/app/src/main/java/io/legado/app/utils/DocumentExtensions.kt index 1d77b2655..15c2e6336 100644 --- a/app/src/main/java/io/legado/app/utils/DocumentExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/DocumentExtensions.kt @@ -95,8 +95,8 @@ object DocumentUtils { } @Throws(Exception::class) - fun listFiles(uri: Uri, regex: Regex? = null): ArrayList { - val docList = arrayListOf() + fun listFiles(uri: Uri, filter: ((file: FileDoc) -> Boolean)? = null): ArrayList { + val docList = arrayListOf() var cursor: Cursor? = null try { val childrenUri = DocumentsContract @@ -118,16 +118,15 @@ object DocumentUtils { val dci = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED) if (cursor.moveToFirst()) { do { - val name = cursor.getString(nci) - if (regex == null || regex.matches(name)) { - val item = DocItem( - name = name, - attr = cursor.getString(mci), - size = cursor.getLong(sci), - date = Date(cursor.getLong(dci)), - uri = DocumentsContract - .buildDocumentUriUsingTree(uri, cursor.getString(ici)) - ) + val item = FileDoc( + name = cursor.getString(nci), + isDir = cursor.getString(mci) == DocumentsContract.Document.MIME_TYPE_DIR, + size = cursor.getLong(sci), + date = Date(cursor.getLong(dci)), + uri = DocumentsContract + .buildDocumentUriUsingTree(uri, cursor.getString(ici)) + ) + if (filter == null || filter.invoke(item)) { docList.add(item) } } while (cursor.moveToNext()) @@ -140,18 +139,16 @@ object DocumentUtils { } @Throws(Exception::class) - fun listFiles(path: String, regex: Regex? = null): ArrayList { - val docItems = arrayListOf() + fun listFiles(path: String, filter: ((file: File) -> Boolean)? = null): ArrayList { + val docItems = arrayListOf() val file = File(path) file.listFiles { pathName -> - regex?.let { - pathName.name.matches(it) - } ?: true + filter?.invoke(pathName) ?: true }?.forEach { docItems.add( - DocItem( + FileDoc( it.name, - it.extension, + it.isDirectory, it.length(), Date(it.lastModified()), Uri.parse(it.absolutePath) @@ -163,18 +160,14 @@ object DocumentUtils { } -data class DocItem( +data class FileDoc( val name: String, - val attr: String, + val isDir: Boolean, val size: Long, val date: Date, val uri: Uri ) { - val isDir: Boolean by lazy { - DocumentsContract.Document.MIME_TYPE_DIR == attr - } - - val isContentPath get() = uri.isContentScheme() + val isContentScheme get() = uri.isContentScheme() } @Throws(Exception::class)