mirror of
https://github.com/gedoor/legado.git
synced 2024-09-01 09:34:25 +08:00
优化
This commit is contained in:
parent
548df96f8a
commit
b05b9a9973
@ -42,21 +42,18 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
|
|||||||
override val binding by viewBinding(ActivityImportBookBinding::inflate)
|
override val binding by viewBinding(ActivityImportBookBinding::inflate)
|
||||||
override val viewModel by viewModels<ImportBookViewModel>()
|
override val viewModel by viewModels<ImportBookViewModel>()
|
||||||
private val bookFileRegex = Regex("(?i).*\\.(txt|epub|umd)")
|
private val bookFileRegex = Regex("(?i).*\\.(txt|epub|umd)")
|
||||||
private var rootDoc: DocumentFile? = null
|
private var rootDoc: FileDoc? = null
|
||||||
private val subDocs = arrayListOf<DocumentFile>()
|
private val subDocs = arrayListOf<FileDoc>()
|
||||||
private val adapter by lazy { ImportBookAdapter(this, this) }
|
private val adapter by lazy { ImportBookAdapter(this, this) }
|
||||||
private val sdPath = FileUtils.getSdCardPath()
|
|
||||||
private var path = sdPath
|
|
||||||
private val selectFolder = registerForActivityResult(HandleFileContract()) {
|
private val selectFolder = registerForActivityResult(HandleFileContract()) {
|
||||||
it.uri?.let { uri ->
|
it.uri?.let { uri ->
|
||||||
if (uri.isContentScheme()) {
|
if (uri.isContentScheme()) {
|
||||||
AppConfig.importBookPath = uri.toString()
|
AppConfig.importBookPath = uri.toString()
|
||||||
initRootDoc()
|
initRootDoc()
|
||||||
} else {
|
} else {
|
||||||
uri.path?.let { path ->
|
AppConfig.importBookPath = uri.path
|
||||||
AppConfig.importBookPath = path
|
initRootDoc()
|
||||||
initRootDoc()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,45 +137,56 @@ class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookV
|
|||||||
}
|
}
|
||||||
lastPath.isContentScheme() -> {
|
lastPath.isContentScheme() -> {
|
||||||
val rootUri = Uri.parse(lastPath)
|
val rootUri = Uri.parse(lastPath)
|
||||||
rootDoc = DocumentFile.fromTreeUri(this, rootUri)
|
kotlin.runCatching {
|
||||||
if (rootDoc == null) {
|
DocumentFile.fromTreeUri(this, rootUri)?.let {
|
||||||
|
subDocs.clear()
|
||||||
|
rootDoc = FileDoc.fromDocumentFile(it)
|
||||||
|
upDocs(rootDoc!!)
|
||||||
|
} ?: let {
|
||||||
|
binding.tvEmptyMsg.visible()
|
||||||
|
selectFolder.launch(null)
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
binding.tvEmptyMsg.visible()
|
binding.tvEmptyMsg.visible()
|
||||||
selectFolder.launch(null)
|
selectFolder.launch(null)
|
||||||
} else {
|
|
||||||
subDocs.clear()
|
|
||||||
upPath()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
|
Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
|
||||||
binding.tvEmptyMsg.visible()
|
binding.tvEmptyMsg.visible()
|
||||||
selectFolder.launch(null)
|
selectFolder.launch(null)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> initRootPath(lastPath)
|
||||||
binding.tvEmptyMsg.visible()
|
|
||||||
PermissionsCompat.Builder(this)
|
|
||||||
.addPermissions(*Permissions.Group.STORAGE)
|
|
||||||
.rationale(R.string.tip_perm_request_storage)
|
|
||||||
.onGranted {
|
|
||||||
rootDoc = null
|
|
||||||
subDocs.clear()
|
|
||||||
path = lastPath
|
|
||||||
upPath()
|
|
||||||
}
|
|
||||||
.request()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initRootPath(path: String) {
|
||||||
|
binding.tvEmptyMsg.visible()
|
||||||
|
PermissionsCompat.Builder(this)
|
||||||
|
.addPermissions(*Permissions.Group.STORAGE)
|
||||||
|
.rationale(R.string.tip_perm_request_storage)
|
||||||
|
.onGranted {
|
||||||
|
kotlin.runCatching {
|
||||||
|
rootDoc = FileDoc.fromFile(File(path))
|
||||||
|
subDocs.clear()
|
||||||
|
upPath()
|
||||||
|
}.onFailure {
|
||||||
|
binding.tvEmptyMsg.visible()
|
||||||
|
selectFolder.launch(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.request()
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun upPath() {
|
private fun upPath() {
|
||||||
rootDoc?.let {
|
rootDoc?.let {
|
||||||
upDocs(it)
|
upDocs(it)
|
||||||
} ?: upFiles()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun upDocs(rootDoc: DocumentFile) {
|
private fun upDocs(rootDoc: FileDoc) {
|
||||||
binding.tvEmptyMsg.gone()
|
binding.tvEmptyMsg.gone()
|
||||||
var path = rootDoc.name.toString() + File.separator
|
var path = rootDoc.name + File.separator
|
||||||
var lastDoc = rootDoc
|
var lastDoc = rootDoc
|
||||||
for (doc in subDocs) {
|
for (doc in subDocs) {
|
||||||
lastDoc = doc
|
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
|
@Synchronized
|
||||||
override fun nextDoc(uri: Uri) {
|
override fun nextDoc(fileDoc: FileDoc) {
|
||||||
if (uri.toString().isContentScheme()) {
|
subDocs.add(fileDoc)
|
||||||
subDocs.add(DocumentFile.fromSingleUri(this, uri)!!)
|
|
||||||
} else {
|
|
||||||
path = uri.path.toString()
|
|
||||||
}
|
|
||||||
upPath()
|
upPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun goBackDir(): Boolean {
|
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()) {
|
return if (subDocs.isNotEmpty()) {
|
||||||
subDocs.removeAt(subDocs.lastIndex)
|
subDocs.removeAt(subDocs.lastIndex)
|
||||||
upPath()
|
upPath()
|
||||||
|
@ -66,7 +66,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
|||||||
holder.itemView.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
getItem(holder.layoutPosition)?.let {
|
getItem(holder.layoutPosition)?.let {
|
||||||
if (it.isDir) {
|
if (it.isDir) {
|
||||||
callBack.nextDoc(it.uri)
|
callBack.nextDoc(it)
|
||||||
} else if (!bookFileNames.contains(it.name)) {
|
} else if (!bookFileNames.contains(it.name)) {
|
||||||
if (!selectedUris.contains(it.toString())) {
|
if (!selectedUris.contains(it.toString())) {
|
||||||
selectedUris.add(it.toString())
|
selectedUris.add(it.toString())
|
||||||
@ -138,7 +138,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CallBack {
|
interface CallBack {
|
||||||
fun nextDoc(uri: Uri)
|
fun nextDoc(fileDoc: FileDoc)
|
||||||
fun upCountView()
|
fun upCountView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,17 +43,15 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun scanDoc(
|
fun scanDoc(
|
||||||
documentFile: DocumentFile,
|
fileDoc: FileDoc,
|
||||||
isRoot: Boolean,
|
isRoot: Boolean,
|
||||||
find: (docItem: FileDoc) -> Unit,
|
find: (docItem: FileDoc) -> Unit,
|
||||||
finally: (() -> Unit)? = null
|
finally: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
DocumentUtils.listFiles(documentFile.uri).forEach { docItem ->
|
DocumentUtils.listFiles(fileDoc.uri).forEach { docItem ->
|
||||||
if (docItem.isDir) {
|
if (docItem.isDir) {
|
||||||
DocumentFile.fromSingleUri(context, docItem.uri)?.let {
|
scanDoc(docItem, false, find)
|
||||||
scanDoc(it, false, find)
|
|
||||||
}
|
|
||||||
} else if (docItem.name.endsWith(".txt", true)
|
} else if (docItem.name.endsWith(".txt", true)
|
||||||
|| docItem.name.endsWith(".epub", 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 {
|
fun readBytes(): ByteArray {
|
||||||
return uri.readBytes(appCtx)
|
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)
|
@Throws(Exception::class)
|
||||||
|
Loading…
Reference in New Issue
Block a user