pull/1415/head
gedoor 3 years ago
parent 92ec2d1057
commit d13a405d6c
  1. 66
      app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
  2. 4
      app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt
  3. 13
      app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt
  4. 8
      app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt
  5. 37
      app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt
  6. 45
      app/src/main/java/io/legado/app/utils/DocumentExtensions.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<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…
Cancel
Save