This commit is contained in:
kunfei
2023-03-31 10:02:24 +08:00
parent 01f18067df
commit 5a0b977dcf
4 changed files with 108 additions and 38 deletions
@@ -1,28 +1,28 @@
package io.legado.app.ui.document package io.legado.app.ui.document
import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.databinding.ActivityFileManageBinding import io.legado.app.databinding.ActivityFileManageBinding
import io.legado.app.databinding.ItemFileBinding import io.legado.app.databinding.ItemFileBinding
import io.legado.app.databinding.ItemPathPickerBinding
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.document.adapter.PathAdapter
import io.legado.app.ui.document.utils.FilePickerIcon import io.legado.app.ui.document.utils.FilePickerIcon
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.ConvertUtils import io.legado.app.utils.ConvertUtils
import io.legado.app.utils.FileDoc
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.list
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import java.io.File
class FileManageActivity : VMBaseActivity<ActivityFileManageBinding, FileManageViewModel>(), class FileManageActivity : VMBaseActivity<ActivityFileManageBinding, FileManageViewModel>() {
PathAdapter.CallBack {
override val binding by viewBinding(ActivityFileManageBinding::inflate) override val binding by viewBinding(ActivityFileManageBinding::inflate)
override val viewModel by viewModels<FileManageViewModel>() override val viewModel by viewModels<FileManageViewModel>()
@@ -30,7 +30,7 @@ class FileManageActivity : VMBaseActivity<ActivityFileManageBinding, FileManageV
binding.titleBar.findViewById(R.id.search_view) binding.titleBar.findViewById(R.id.search_view)
} }
private val pathAdapter by lazy { private val pathAdapter by lazy {
PathAdapter(this, this) PathAdapter()
} }
private val fileAdapter by lazy { private val fileAdapter by lazy {
FileAdapter() FileAdapter()
@@ -39,14 +39,14 @@ class FileManageActivity : VMBaseActivity<ActivityFileManageBinding, FileManageV
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
initView() initView()
initSearchView() initSearchView()
initData() viewModel.upFiles(viewModel.rootDoc)
} }
private fun initView() { private fun initView() {
binding.rvPath.layoutManager = LinearLayoutManager(this) binding.rvPath.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
binding.rvPath.addItemDecoration(VerticalDivider(this))
binding.rvPath.adapter = pathAdapter binding.rvPath.adapter = pathAdapter
binding.recyclerView.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.addItemDecoration(VerticalDivider(this))
binding.recyclerView.adapter = fileAdapter binding.recyclerView.adapter = fileAdapter
} }
@@ -68,44 +68,101 @@ class FileManageActivity : VMBaseActivity<ActivityFileManageBinding, FileManageV
}) })
} }
private fun initData() { override fun observeLiveBus() {
viewModel.rootDoc?.list()?.let { viewModel.filesLiveData.observe(this) {
fileAdapter.setItems(it) fileAdapter.setItems(it)
} }
} }
override fun onPathClick(position: Int) { @SuppressLint("SetTextI18n")
inner class PathAdapter :
RecyclerAdapter<File, ItemPathPickerBinding>(this@FileManageActivity) {
private val arrowIcon = ConvertUtils.toDrawable(FilePickerIcon.getArrow())
init {
addHeaderView {
ItemPathPickerBinding.inflate(inflater, it, false).apply {
textView.text = "root"
imageView.setImageDrawable(arrowIcon)
root.setOnClickListener {
viewModel.subDocs.clear()
setItems(viewModel.subDocs)
viewModel.upFiles(viewModel.rootDoc)
}
}
}
}
override fun getViewBinding(parent: ViewGroup): ItemPathPickerBinding {
return ItemPathPickerBinding.inflate(inflater, parent, false).apply {
imageView.setImageDrawable(arrowIcon)
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemPathPickerBinding) {
binding.root.setOnClickListener {
viewModel.subDocs = viewModel.subDocs.subList(0, holder.layoutPosition)
setItems(viewModel.subDocs)
viewModel.upFiles(viewModel.subDocs.lastOrNull())
}
}
override fun convert(
holder: ItemViewHolder,
binding: ItemPathPickerBinding,
item: File,
payloads: MutableList<Any>
) {
binding.textView.text = item.name
}
} }
inner class FileAdapter : RecyclerAdapter<FileDoc, ItemFileBinding>(this@FileManageActivity) { inner class FileAdapter : RecyclerAdapter<File, ItemFileBinding>(this@FileManageActivity) {
private val upIcon = ConvertUtils.toDrawable(FilePickerIcon.getUpDir())!! private val upIcon = ConvertUtils.toDrawable(FilePickerIcon.getUpDir())!!
private val folderIcon = ConvertUtils.toDrawable(FilePickerIcon.getFolder())!! private val folderIcon = ConvertUtils.toDrawable(FilePickerIcon.getFolder())!!
private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFile())!! private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFile())!!
private val dirParent = ".."
override fun getViewBinding(parent: ViewGroup): ItemFileBinding { override fun getViewBinding(parent: ViewGroup): ItemFileBinding {
return ItemFileBinding.inflate(inflater, parent, false) return ItemFileBinding.inflate(inflater, parent, false)
} }
override fun registerListener(holder: ItemViewHolder, binding: ItemFileBinding) { override fun registerListener(holder: ItemViewHolder, binding: ItemFileBinding) {
binding.root.setOnClickListener {
val item = getItemByLayoutPosition(holder.layoutPosition)
item?.let {
if (item == (viewModel.subDocs.lastOrNull() ?: viewModel.rootDoc)) {
viewModel.subDocs.removeLastOrNull()
pathAdapter.setItems(viewModel.subDocs)
viewModel.upFiles(viewModel.subDocs.lastOrNull() ?: viewModel.rootDoc)
} else if (item.isDirectory) {
viewModel.subDocs.add(item)
pathAdapter.setItems(viewModel.subDocs)
viewModel.upFiles(item)
}
}
}
} }
override fun convert( override fun convert(
holder: ItemViewHolder, holder: ItemViewHolder,
binding: ItemFileBinding, binding: ItemFileBinding,
item: FileDoc, item: File,
payloads: MutableList<Any> payloads: MutableList<Any>
) { ) {
if (!item.isDir) { if (item == (viewModel.subDocs.lastOrNull() ?: viewModel.rootDoc)) {
binding.imageView.setImageDrawable(fileIcon)
} else if (holder.layoutPosition == 0 && viewModel.subDocs.isNotEmpty()) {
binding.imageView.setImageDrawable(upIcon) binding.imageView.setImageDrawable(upIcon)
} else { binding.textView.text = dirParent
} else if (item.isDirectory) {
binding.imageView.setImageDrawable(folderIcon) binding.imageView.setImageDrawable(folderIcon)
} binding.textView.text = item.name
} else {
binding.imageView.setImageDrawable(fileIcon)
binding.textView.text = item.name binding.textView.text = item.name
} }
}
} }
@@ -1,14 +1,36 @@
package io.legado.app.ui.document package io.legado.app.ui.document
import android.app.Application import android.app.Application
import androidx.lifecycle.MutableLiveData
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.utils.FileDoc import io.legado.app.utils.toastOnUi
import java.io.File
class FileManageViewModel(application: Application) : BaseViewModel(application) { class FileManageViewModel(application: Application) : BaseViewModel(application) {
val rootDoc = context.getExternalFilesDir(null)?.parentFile?.let { val rootDoc = context.getExternalFilesDir(null)?.parentFile
FileDoc.fromFile(it) var subDocs = mutableListOf<File>()
val filesLiveData = MutableLiveData<List<File>>()
fun upFiles(parentFile: File?) {
execute {
if (parentFile == rootDoc) {
parentFile?.listFiles()?.toList()
} else {
val list = arrayListOf(parentFile)
parentFile?.listFiles()?.let {
list.addAll(it)
} }
val subDocs = arrayListOf<FileDoc>() list
}
}.onStart {
filesLiveData.postValue(emptyList())
}.onSuccess {
filesLiveData.postValue(it ?: emptyList())
}.onError {
context.toastOnUi(it.localizedMessage)
}
}
} }
@@ -27,6 +27,8 @@ class FileAdapter(context: Context, val callBack: CallBack) :
private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFile())!! private val fileIcon = ConvertUtils.toDrawable(FilePickerIcon.getFile())!!
private val primaryTextColor = context.getPrimaryTextColor(!AppConfig.isNightTheme) private val primaryTextColor = context.getPrimaryTextColor(!AppConfig.isNightTheme)
private val disabledTextColor = context.getPrimaryDisabledTextColor(!AppConfig.isNightTheme) private val disabledTextColor = context.getPrimaryDisabledTextColor(!AppConfig.isNightTheme)
private val dirRoot = "."
private val dirParent = ".."
fun loadData(path: String?) { fun loadData(path: String?) {
if (path == null) { if (path == null) {
@@ -42,7 +44,7 @@ class FileAdapter(context: Context, val callBack: CallBack) :
val fileRoot = FileItem( val fileRoot = FileItem(
isDirectory = true, isDirectory = true,
icon = homeIcon, icon = homeIcon,
name = DIR_ROOT, name = dirRoot,
path = rootPath ?: path path = rootPath ?: path
) )
data.add(fileRoot) data.add(fileRoot)
@@ -52,7 +54,7 @@ class FileAdapter(context: Context, val callBack: CallBack) :
val fileParent = FileItem( val fileParent = FileItem(
isDirectory = true, isDirectory = true,
icon = upIcon, icon = upIcon,
name = DIR_PARENT, name = dirParent,
path = File(path).parent ?: "" path = File(path).parent ?: ""
) )
data.add(fileParent) data.add(fileParent)
@@ -152,10 +154,5 @@ class FileAdapter(context: Context, val callBack: CallBack) :
var isShowHideDir: Boolean var isShowHideDir: Boolean
} }
companion object {
const val DIR_ROOT = "."
const val DIR_PARENT = ".."
}
} }
@@ -24,18 +24,12 @@
android:elevation="5dp" android:elevation="5dp"
app:layout_constraintTop_toBottomOf="@+id/titleBar" /> app:layout_constraintTop_toBottomOf="@+id/titleBar" />
<io.legado.app.ui.widget.anima.RefreshProgressBar
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
app:layout_constraintTop_toBottomOf="@id/rv_path" />
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
app:layout_constraintBottom_toTopOf="@id/select_action_bar" app:layout_constraintBottom_toTopOf="@id/select_action_bar"
app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar"> app:layout_constraintTop_toBottomOf="@id/rv_path">
<io.legado.app.ui.widget.recycler.scroller.FastScrollRecyclerView <io.legado.app.ui.widget.recycler.scroller.FastScrollRecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"