1.优化修改名字dialog的复用

2.优化书签dialog的数据观察
3.添加修改书签名称功能
This commit is contained in:
ocean 2025-09-18 11:46:44 +08:00
parent 5fea68bd95
commit 82bf542cbb
9 changed files with 142 additions and 59 deletions

View File

@ -22,6 +22,7 @@ sealed class FileActionEvent {
object NoticeReload : FileActionEvent()
data class AddBookmark(val success: Boolean) : FileActionEvent()
data class UpdateBookmark(val success: Boolean) : FileActionEvent()
data class DeleteBookmark(val success: Boolean) : FileActionEvent()
data class DeleteAllBookmark(val success: Boolean) : FileActionEvent()
}

View File

@ -0,0 +1,6 @@
package com.all.pdfreader.pro.app.model
enum class RenameType {
FILE, // 修改文件名
BOOKMARK // 修改书签名
}

View File

@ -3,10 +3,8 @@ package com.all.pdfreader.pro.app.ui.act
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import android.view.View
import androidx.core.os.HandlerCompat.postDelayed
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.all.pdfreader.pro.app.R

View File

@ -10,7 +10,7 @@ import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
class BookmarkAdapter(
private var list: MutableList<BookmarkEntity>,
private val onItemClick: (BookmarkEntity) -> Unit,
private val onEditClick: (BookmarkEntity) -> Unit,
private val onEditClick: (BookmarkEntity, Int) -> Unit,
private val onDeleteClick: (BookmarkEntity, Int) -> Unit,
) : RecyclerView.Adapter<BookmarkAdapter.PdfViewHolder>() {
@ -35,7 +35,7 @@ class BookmarkAdapter(
onItemClick(item)
}
holder.binding.editBtn.setOnClickListener {
onEditClick(item)
onEditClick(item, position)
}
holder.binding.deleteBtn.setOnClickListener {
onDeleteClick(item, position)
@ -51,6 +51,16 @@ class BookmarkAdapter(
notifyDataSetChanged()
}
fun updateItemChanged(updatedBookmark: BookmarkEntity) {
val index = list.indexOfFirst { it.id == updatedBookmark.id }
if (index != -1) {
list = list.toMutableList().apply {
this[index] = updatedBookmark
}
notifyItemChanged(index)
}
}
fun removeItem(position: Int) {
list.removeAt(position)
notifyItemRemoved(position)

View File

@ -10,6 +10,7 @@ import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogBookmarksBinding
import com.all.pdfreader.pro.app.model.RenameType
import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.ui.adapter.BookmarkAdapter
@ -17,10 +18,8 @@ import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class BookmarksDialogFragment(
private val pdfDocument: PdfDocumentEntity,
private val onJumpPage: (Int) -> Unit
) :
BottomSheetDialogFragment() {
private val pdfDocument: PdfDocumentEntity, private val onJumpPage: (Int) -> Unit
) : BottomSheetDialogFragment() {
private lateinit var binding: DialogBookmarksBinding
private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel
@ -58,24 +57,29 @@ class BookmarksDialogFragment(
showToast(getString(R.string.file_not))
dismiss()
}
//观察书签数据
viewModel.pdfBookmark.observe(this) { list ->
Log.d("ocean","BookmarksDialogFragment observe")
list?.let {
viewModel.pdfBookmark.value?.let {
bookmarks = it
initView()
setupOnClick()
} ?: run {
showToast(getString(R.string.bookmark_loading))
dismiss()
}
}
viewModel.getBookmarks(pdfDocument.filePath)
}
private fun initView() {
adapter = BookmarkAdapter(list = mutableListOf(), onItemClick = { bookmark ->
onJumpPage(bookmark.pageNumber)
dismiss()
}, onEditClick = { bookmark ->
}, onEditClick = { bookmark, position ->
RenameDialogFragment(RenameType.BOOKMARK, bookmark, onOkClick = { updatedBookmark ->
bookmarks = bookmarks.map {//更新外部数据
if (it.id == updatedBookmark.id) updatedBookmark else it
}
adapter.updateItemChanged(updatedBookmark)//更新adapter数据
}).show(
parentFragmentManager, "BookmarksDialogFragment"
)
}, onDeleteClick = { bookmark, position ->
adapter.removeItem(position)
bookmarks = bookmarks.filter { it.id != bookmark.id }
@ -83,7 +87,11 @@ class BookmarksDialogFragment(
})
binding.bookmarksPageRv.layoutManager = LinearLayoutManager(requireContext())
binding.bookmarksPageRv.adapter = adapter
updateUi()
updateAdapter()
}
private fun updateUi(){
if (bookmarks.isEmpty()) {
binding.noBookmarksPageLayout.visibility = View.VISIBLE//显示没有书签的提示布局
binding.bookmarksDisplayLayout.visibility = View.GONE//隐藏显示内容的布局
@ -106,8 +114,6 @@ class BookmarksDialogFragment(
binding.addBtn.setBackgroundResource(R.drawable.dr_click_btn_red_bg)
binding.addIv.setImageResource(R.drawable.add_icon_white)
}
updateAdapter()
}
}
@ -126,6 +132,7 @@ class BookmarksDialogFragment(
viewModel.deleteAllBookmark(pdfDocument.filePath)
adapter.removeAllItems()
bookmarks = emptyList()
updateUi()
}).show(parentFragmentManager, "DeleteDialogFragment")
}
}

View File

@ -10,6 +10,7 @@ import androidx.fragment.app.activityViewModels
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding
import com.all.pdfreader.pro.app.model.PrintResult
import com.all.pdfreader.pro.app.model.RenameType
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.util.AppUtils.dpToPx
import com.all.pdfreader.pro.app.util.AppUtils.printPdfFile
@ -95,7 +96,10 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
dismiss()
}
binding.renameFileBtn.setOnClickListener {
RenameDialogFragment().show(parentFragmentManager, "ListMoreDialogFragment")
RenameDialogFragment(RenameType.FILE).show(
parentFragmentManager,
"ListMoreDialogFragment"
)
dismiss()
}
binding.deleteFileBtn.setOnClickListener {

View File

@ -13,17 +13,21 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogRenameFileBinding
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.model.RenameType
import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
import com.all.pdfreader.pro.app.util.FileUtils
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
import java.io.File
class RenameDialogFragment() : DialogFragment() {
class RenameDialogFragment(
private val type: RenameType,
private val bookmark: BookmarkEntity? = null,
private val onOkClick: (BookmarkEntity) -> Unit= {}
) : DialogFragment() {
private lateinit var binding: DialogRenameFileBinding
private val viewModel: PdfViewModel by activityViewModels()
private lateinit var pdfDocument: PdfDocumentEntity
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@ -47,35 +51,62 @@ class RenameDialogFragment() : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
when (type) {
RenameType.FILE -> {
viewModel.pdfDocument.value?.let {
pdfDocument = it
initView()
setupOnClick()
initView(it.fileName)
setupOnClick(it.fileName, it.filePath, null)
} ?: run {
showToast(getString(R.string.file_not))
dismiss()
}
}
private fun initView() {
binding.etName.showKeyboard()
binding.etName.setText(FileUtils.removeFileExtension(pdfDocument.fileName))
// 保持光标在末尾
binding.etName.setSelection(binding.etName.text?.length ?: 0)
RenameType.BOOKMARK -> {
bookmark?.let {
initView(it.label)
setupOnClick(it.label, it.filePath, it)
} ?: run {
showToast(getString(R.string.file_not))
dismiss()
}
}
}
}
private fun setupOnClick() {
private fun initView(name: String) {
binding.etName.showKeyboard()
binding.etName.setText(FileUtils.removeFileExtension(name))
// 保持光标在末尾
binding.etName.setSelection(binding.etName.text?.length ?: 0)
}
private fun setupOnClick(oldName: String, filePath: String, bookmark: BookmarkEntity?) {
binding.tvCancel.setOnClickListener {
dismiss()
}
binding.tvConfirm.setOnClickListener {
when (type) {
RenameType.FILE -> {
val text = binding.etName.text.toString()
if (validateEnter(text)) {
viewModel.renamePdf(pdfDocument.filePath, text)
if (validateEnter(text, oldName, filePath)) {
viewModel.renamePdf(filePath, text)
dismiss()
}
}
RenameType.BOOKMARK -> {
val text = binding.etName.text.toString()
if (validateEnter(text, oldName, filePath)) {
val new = bookmark?.copy(label = text)!!
viewModel.updateBookmark(new)
onOkClick(new)
dismiss()
}
}
}
}
binding.etName.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@ -86,19 +117,13 @@ class RenameDialogFragment() : DialogFragment() {
})
}
private fun validateEnter(name: String): Boolean {
private fun validateEnter(name: String, oldName: String, filePath: String): Boolean {
// 不允许为空
if (name.isBlank()) {
binding.tilName.error = getString(R.string.name_not_empty)
return false
}
// 名字未做修改(因展示的时候去掉了扩展名,则判断的时候也去掉)
if (name == FileUtils.removeFileExtension(pdfDocument.fileName)) {
binding.tilName.error = getString(R.string.name_not_changed)
return false
}
// 含有非法字符
val invalidChars = "[/\\\\:*?\"<>|.]".toRegex()
if (invalidChars.containsMatchIn(name)) {
@ -106,18 +131,37 @@ class RenameDialogFragment() : DialogFragment() {
return false
}
// 长度过长
when (type) {
//只有修改文件名称时,才进行以下判断
RenameType.FILE -> {
if (name.length > 255) {
binding.tilName.error = getString(R.string.name_too_long)
return false
}
// 名字未做修改(因展示的时候去掉了扩展名,则判断的时候也去掉)
if (name == FileUtils.removeFileExtension(oldName)) {
binding.tilName.error = getString(R.string.name_not_changed)
return false
}
// 与现有文件重名
val parentDir = File(pdfDocument.filePath).parentFile
val parentDir = File(filePath).parentFile
if (parentDir != null && File(parentDir, name).exists()) {
binding.tilName.error = getString(R.string.name_already_exists)
return false
}
}
RenameType.BOOKMARK -> {
if (name.length > 50) {
binding.tilName.error = getString(R.string.name_too_long)
return false
}
if (name == oldName) {
binding.tilName.error = getString(R.string.name_not_changed)
return false
}
}
}
// 禁止开头/结尾空格
if (name != name.trim()) {

View File

@ -18,6 +18,7 @@ import com.all.pdfreader.pro.app.util.FileUtils.isPdfEncrypted
import com.all.pdfreader.pro.app.util.PdfMetadataExtractor
import com.all.pdfreader.pro.app.util.PdfSecurityUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
@ -202,7 +203,7 @@ class PdfViewModel : ViewModel() {
fun getBookmarks(filePath: String) {
viewModelScope.launch {
Log.d("ocean", "getBookmarks->filePath: $filePath")
pdfRepository.getBookmarksByPdf(filePath).collect { bookmarks ->
pdfRepository.getBookmarksByPdf(filePath).distinctUntilChanged().collect { bookmarks ->
_pdfBookmark.value = bookmarks
}
}
@ -217,10 +218,20 @@ class PdfViewModel : ViewModel() {
}
}
fun updateBookmark(bookmark: BookmarkEntity){
viewModelScope.launch {
val int = pdfRepository.updateBookmark(bookmark)
val success = int > 0
Log.d("ocean", "updateBookmark->success: $success")
_fileActionEvent.postValue(FileActionEvent.UpdateBookmark(success))
}
}
fun deleteBookMark(bookmark: BookmarkEntity) {
viewModelScope.launch {
val int = pdfRepository.deleteBookmark(bookmark)
val success = int > 0//受影响行数大于0
Log.d("ocean", "deleteBookmark->success: $success")
_fileActionEvent.postValue(FileActionEvent.DeleteBookmark(success))
}
}
@ -229,6 +240,7 @@ class PdfViewModel : ViewModel() {
viewModelScope.launch {
val int = pdfRepository.deleteAllBookmark(filePath)
val success = int > 0
Log.d("ocean", "deleteAllBookmark->success: $success")
_fileActionEvent.postValue(FileActionEvent.DeleteAllBookmark(success))
}
}

View File

@ -113,4 +113,5 @@
<string name="bookmark_remove">Bookmark remove</string>
<string name="delete_bookmarks_title">Delete Bookmarks</string>
<string name="delete_bookmarks_desc">Are you sure you want to delete all Bookmarks?</string>
<string name="bookmark_loading">Loading bookmarks, please try again later</string>
</resources>