mirror of
https://github.com/gedoor/legado.git
synced 2024-09-01 09:34:25 +08:00
优化
This commit is contained in:
parent
92ec2d1057
commit
d13a405d6c
@ -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<ActivityImportBookBinding, ImportBookV
|
||||
|
||||
override val binding by viewBinding(ActivityImportBookBinding::inflate)
|
||||
override val viewModel by viewModels<ImportBookViewModel>()
|
||||
|
||||
private val bookFileRegex = Regex("(?i).*\\.(txt|epub|umd)")
|
||||
private var rootDoc: DocumentFile? = null
|
||||
private val subDocs = arrayListOf<DocumentFile>()
|
||||
private val adapter by lazy { ImportBookAdapter(this, this) }
|
||||
@ -191,17 +189,11 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
|
||||
adapter.clearItems()
|
||||
launch(IO) {
|
||||
runCatching {
|
||||
val docList = DocumentUtils.listFiles(lastDoc.uri)
|
||||
for (i in docList.lastIndex downTo 0) {
|
||||
val item = docList[i]
|
||||
if (item.name.startsWith(".")) {
|
||||
docList.removeAt(i)
|
||||
} else if (!item.isDir
|
||||
&& !item.name.endsWith(".txt", true)
|
||||
&& !item.name.endsWith(".epub", true)
|
||||
&& !item.name.endsWith(".umd", true)
|
||||
) {
|
||||
docList.removeAt(i)
|
||||
val docList = DocumentUtils.listFiles(lastDoc.uri) { item ->
|
||||
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<ActivityImportBookBinding, ImportBookV
|
||||
private fun upFiles() {
|
||||
binding.tvEmptyMsg.gone()
|
||||
binding.tvPath.text = path.replace(sdPath, "SD")
|
||||
val docList = arrayListOf<DocItem>()
|
||||
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<ActivityImportBookBinding, ImportBookV
|
||||
}
|
||||
}
|
||||
|
||||
private val find: (docItem: DocItem) -> Unit = {
|
||||
private val find: (docItem: FileDoc) -> Unit = {
|
||||
launch {
|
||||
adapter.addItem(it)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import io.legado.app.utils.*
|
||||
|
||||
|
||||
class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
RecyclerAdapter<DocItem, ItemImportBookBinding>(context) {
|
||||
RecyclerAdapter<FileDoc, ItemImportBookBinding>(context) {
|
||||
var selectedUris = hashSetOf<String>()
|
||||
var checkableCount = 0
|
||||
private var bookFileNames = arrayListOf<String>()
|
||||
@ -29,7 +29,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
||||
override fun convert(
|
||||
holder: ItemViewHolder,
|
||||
binding: ItemImportBookBinding,
|
||||
item: DocItem,
|
||||
item: FileDoc,
|
||||
payloads: MutableList<Any>
|
||||
) {
|
||||
binding.run {
|
||||
|
@ -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)
|
||||
|
@ -13,7 +13,7 @@ import java.io.File
|
||||
import java.net.URLDecoder
|
||||
|
||||
class FontAdapter(context: Context, curFilePath: String, val callBack: CallBack) :
|
||||
RecyclerAdapter<DocItem, ItemFontBinding>(context) {
|
||||
RecyclerAdapter<FileDoc, ItemFontBinding>(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<Any>
|
||||
) {
|
||||
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)
|
||||
}
|
||||
}
|
@ -126,29 +126,18 @@ class FontSelectDialog : BaseDialogFragment(R.layout.dialog_font_select),
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLocalFonts(): ArrayList<DocItem> {
|
||||
val fontItems = arrayListOf<DocItem>()
|
||||
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<FileDoc> {
|
||||
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<DocItem>,
|
||||
items2: ArrayList<DocItem>
|
||||
): List<DocItem> {
|
||||
items1: ArrayList<FileDoc>,
|
||||
items2: ArrayList<FileDoc>
|
||||
): List<FileDoc> {
|
||||
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())
|
||||
|
@ -95,8 +95,8 @@ object DocumentUtils {
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun listFiles(uri: Uri, regex: Regex? = null): ArrayList<DocItem> {
|
||||
val docList = arrayListOf<DocItem>()
|
||||
fun listFiles(uri: Uri, filter: ((file: FileDoc) -> Boolean)? = null): ArrayList<FileDoc> {
|
||||
val docList = arrayListOf<FileDoc>()
|
||||
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<DocItem> {
|
||||
val docItems = arrayListOf<DocItem>()
|
||||
fun listFiles(path: String, filter: ((file: File) -> Boolean)? = null): ArrayList<FileDoc> {
|
||||
val docItems = arrayListOf<FileDoc>()
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user