pull/1403/head
gedoor 3 years ago
parent 548df96f8a
commit b05b9a9973
  1. 105
      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. 36
      app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt
  4. 24
      app/src/main/java/io/legado/app/utils/DocumentExtensions.kt

@ -42,24 +42,21 @@ 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 var rootDoc: FileDoc? = null
private val subDocs = arrayListOf<FileDoc>()
private val adapter by lazy { ImportBookAdapter(this, this) }
private val sdPath = FileUtils.getSdCardPath()
private var path = sdPath
private val selectFolder = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
if (uri.isContentScheme()) {
AppConfig.importBookPath = uri.toString()
initRootDoc()
} else {
uri.path?.let { path ->
AppConfig.importBookPath = path
AppConfig.importBookPath = uri.path
initRootDoc()
}
}
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
initView()
@ -140,45 +137,56 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
}
lastPath.isContentScheme() -> {
val rootUri = Uri.parse(lastPath)
rootDoc = DocumentFile.fromTreeUri(this, rootUri)
if (rootDoc == null) {
kotlin.runCatching {
DocumentFile.fromTreeUri(this, rootUri)?.let {
subDocs.clear()
rootDoc = FileDoc.fromDocumentFile(it)
upDocs(rootDoc!!)
} ?: let {
binding.tvEmptyMsg.visible()
selectFolder.launch(null)
}
}.onFailure {
binding.tvEmptyMsg.visible()
selectFolder.launch(null)
} else {
subDocs.clear()
upPath()
}
}
Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
binding.tvEmptyMsg.visible()
selectFolder.launch(null)
}
else -> {
else -> initRootPath(lastPath)
}
}
private fun initRootPath(path: String) {
binding.tvEmptyMsg.visible()
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
rootDoc = null
kotlin.runCatching {
rootDoc = FileDoc.fromFile(File(path))
subDocs.clear()
path = lastPath
upPath()
}
.request()
}.onFailure {
binding.tvEmptyMsg.visible()
selectFolder.launch(null)
}
}
.request()
}
@Synchronized
private fun upPath() {
rootDoc?.let {
upDocs(it)
} ?: upFiles()
}
}
private fun upDocs(rootDoc: DocumentFile) {
private fun upDocs(rootDoc: FileDoc) {
binding.tvEmptyMsg.gone()
var path = rootDoc.name.toString() + File.separator
var path = rootDoc.name + File.separator
var lastDoc = rootDoc
for (doc in subDocs) {
lastDoc = doc
@ -206,29 +214,6 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
}
}
private fun upFiles() {
binding.tvEmptyMsg.gone()
binding.tvPath.text = path.replace(sdPath, "SD")
adapter.clearItems()
launch(IO) {
kotlin.runCatching {
val docList = DocumentUtils.listFiles(path) {
when {
it.name.startsWith(".") -> false
it.isDir -> true
else -> it.name.matches(bookFileRegex)
}
}
docList.sortWith(compareBy({ !it.isDir }, { it.name }))
withContext(Main) {
adapter.setItems(docList)
}
}.onFailure {
toastOnUi("获取文件列表出错\n${it.localizedMessage}")
}
}
}
/**
* 扫描当前文件夹
*/
@ -244,22 +229,6 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
}
}
}
} ?: let {
val lastPath = AppConfig.importBookPath
if (lastPath.isNullOrEmpty()) {
toastOnUi(R.string.empty_msg_import_book)
} else {
adapter.clearItems()
val file = File(path)
binding.refreshProgressBar.isAutoLoading = true
launch(IO) {
viewModel.scanFile(file, true, find) {
launch {
binding.refreshProgressBar.isAutoLoading = false
}
}
}
}
}
}
@ -285,27 +254,13 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
}
@Synchronized
override fun nextDoc(uri: Uri) {
if (uri.toString().isContentScheme()) {
subDocs.add(DocumentFile.fromSingleUri(this, uri)!!)
} else {
path = uri.path.toString()
}
override fun nextDoc(fileDoc: FileDoc) {
subDocs.add(fileDoc)
upPath()
}
@Synchronized
private fun goBackDir(): Boolean {
if (rootDoc == null) {
if (path != sdPath) {
File(path).parent?.let {
path = it
upPath()
return true
}
}
return false
}
return if (subDocs.isNotEmpty()) {
subDocs.removeAt(subDocs.lastIndex)
upPath()

@ -66,7 +66,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
holder.itemView.setOnClickListener {
getItem(holder.layoutPosition)?.let {
if (it.isDir) {
callBack.nextDoc(it.uri)
callBack.nextDoc(it)
} else if (!bookFileNames.contains(it.name)) {
if (!selectedUris.contains(it.toString())) {
selectedUris.add(it.toString())
@ -138,7 +138,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
}
interface CallBack {
fun nextDoc(uri: Uri)
fun nextDoc(fileDoc: FileDoc)
fun upCountView()
}

@ -43,17 +43,15 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
}
fun scanDoc(
documentFile: DocumentFile,
fileDoc: FileDoc,
isRoot: Boolean,
find: (docItem: FileDoc) -> Unit,
finally: (() -> Unit)? = null
) {
kotlin.runCatching {
DocumentUtils.listFiles(documentFile.uri).forEach { docItem ->
DocumentUtils.listFiles(fileDoc.uri).forEach { docItem ->
if (docItem.isDir) {
DocumentFile.fromSingleUri(context, docItem.uri)?.let {
scanDoc(it, false, find)
}
scanDoc(docItem, false, find)
} else if (docItem.name.endsWith(".txt", true)
|| docItem.name.endsWith(".epub", true)
) {
@ -68,32 +66,4 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
}
}
fun scanFile(
file: File,
isRoot: Boolean,
find: (docItem: FileDoc) -> Unit,
finally: (() -> Unit)? = null
) {
file.listFiles()?.forEach {
if (it.isDirectory) {
scanFile(it, false, find)
} else if (it.name.endsWith(".txt", true)
|| it.name.endsWith(".epub", true)
) {
find(
FileDoc(
it.name,
it.isDirectory,
it.length(),
Date(it.lastModified()),
Uri.parse(it.absolutePath)
)
)
}
}
if (isRoot) {
finally?.invoke()
}
}
}

@ -179,6 +179,30 @@ data class FileDoc(
fun readBytes(): ByteArray {
return uri.readBytes(appCtx)
}
companion object {
fun fromDocumentFile(doc: DocumentFile): FileDoc {
return FileDoc(
name = doc.name ?: "",
isDir = doc.isDirectory,
size = doc.length(),
date = Date(doc.lastModified()),
uri = doc.uri
)
}
fun fromFile(file: File): FileDoc {
return FileDoc(
name = file.name,
isDir = file.isDirectory,
size = file.length(),
date = Date(file.lastModified()),
uri = Uri.fromFile(file)
)
}
}
}
@Throws(Exception::class)

Loading…
Cancel
Save