From 5fea68bd952b810496a6964103087a0077b1f831 Mon Sep 17 00:00:00 2001 From: ocean <503259349@qq.com> Date: Wed, 17 Sep 2025 18:40:36 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=E4=B9=A6=E7=AD=BE=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=88=E6=B7=BB=E5=8A=A0=E4=B8=8E=E5=88=A0=E9=99=A4?= =?UTF-8?q?=EF=BC=89=202.=E4=BC=98=E5=8C=96=E9=98=85=E8=AF=BB=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E6=BB=9A=E5=8A=A8=E6=A0=87=E7=AD=BE=E5=9C=A8=E6=A8=AA?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=8B=E7=9A=84=E6=B7=A1=E5=87=BA=E6=B7=A1?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pro/app/model/FileActionEvent.kt | 19 +-- .../pdfreader/pro/app/room/dao/BookmarkDao.kt | 24 +-- .../pro/app/room/repository/PdfRepository.kt | 16 +- .../pro/app/ui/act/PdfViewActivity.kt | 39 ++++- .../pro/app/ui/adapter/BookmarkAdapter.kt | 66 ++++++++ .../app/ui/dialog/BookmarksDialogFragment.kt | 111 +++++++++++-- .../pro/app/ui/dialog/DeleteDialogFragment.kt | 23 +-- .../app/ui/dialog/ListMoreDialogFragment.kt | 7 +- .../app/ui/dialog/ViewModelDialogFragment.kt | 2 +- .../pro/app/ui/view/CustomScrollHandle.java | 30 ++-- .../pro/app/viewmodel/PdfViewModel.kt | 53 +++++- .../main/res/drawable/add_bookmarks_white.xml | 12 ++ app/src/main/res/drawable/add_icon_grey.xml | 22 +++ app/src/main/res/drawable/add_icon_white.xml | 22 +++ .../main/res/drawable/bookmark_icon_red.xml | 17 ++ app/src/main/res/drawable/delete_cha_icon.xml | 26 +++ app/src/main/res/drawable/dr_bookmarks_bg.xml | 5 + .../res/drawable/dr_btn_not_clickable_bg.xml | 6 + app/src/main/res/drawable/dr_click_btn_bg.xml | 4 +- .../main/res/drawable/dr_click_btn_red_bg.xml | 4 +- app/src/main/res/drawable/dr_dot_red.xml | 5 + .../res/drawable/dr_item_bookmark_page_bg.xml | 6 + app/src/main/res/drawable/edit_icon.xml | 26 +++ app/src/main/res/drawable/page_icon.xml | 35 ++++ app/src/main/res/layout/activity_main.xml | 18 +- app/src/main/res/layout/activity_pdf_view.xml | 57 +++++-- .../res/layout/adapter_item_bookmark_page.xml | 74 +++++++++ app/src/main/res/layout/dialog_bookmarks.xml | 157 +++++++++++++++++- app/src/main/res/layout/dialog_delete.xml | 14 +- app/src/main/res/layout/dialog_permission.xml | 9 +- app/src/main/res/layout/dialog_sort.xml | 1 + app/src/main/res/layout/dialog_view_model.xml | 1 + app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 12 ++ 34 files changed, 791 insertions(+), 133 deletions(-) create mode 100644 app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/BookmarkAdapter.kt create mode 100644 app/src/main/res/drawable/add_bookmarks_white.xml create mode 100644 app/src/main/res/drawable/add_icon_grey.xml create mode 100644 app/src/main/res/drawable/add_icon_white.xml create mode 100644 app/src/main/res/drawable/bookmark_icon_red.xml create mode 100644 app/src/main/res/drawable/delete_cha_icon.xml create mode 100644 app/src/main/res/drawable/dr_bookmarks_bg.xml create mode 100644 app/src/main/res/drawable/dr_btn_not_clickable_bg.xml create mode 100644 app/src/main/res/drawable/dr_dot_red.xml create mode 100644 app/src/main/res/drawable/dr_item_bookmark_page_bg.xml create mode 100644 app/src/main/res/drawable/edit_icon.xml create mode 100644 app/src/main/res/drawable/page_icon.xml create mode 100644 app/src/main/res/layout/adapter_item_bookmark_page.xml diff --git a/app/src/main/java/com/all/pdfreader/pro/app/model/FileActionEvent.kt b/app/src/main/java/com/all/pdfreader/pro/app/model/FileActionEvent.kt index d4769c0..e84d8de 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/model/FileActionEvent.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/model/FileActionEvent.kt @@ -1,7 +1,5 @@ package com.all.pdfreader.pro.app.model -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData import java.io.File sealed class FileActionEvent { @@ -15,22 +13,15 @@ sealed class FileActionEvent { enum class Status { START, COMPLETE } } - data class RemovePassword(val status: Status, val success: Boolean? = null) : FileActionEvent() { + data class RemovePassword(val status: Status, val success: Boolean? = null) : + FileActionEvent() { enum class Status { START, COMPLETE } } //只做通知,不携带任何数据,使用object。 object NoticeReload : FileActionEvent() - inline fun LiveData.observeEvent( - owner: LifecycleOwner, - crossinline handler: (T) -> Unit - ) { - this.observe(owner) { event -> - if (event is T) { - handler(event) - } - } - } - + data class AddBookmark(val success: Boolean) : FileActionEvent() + data class DeleteBookmark(val success: Boolean) : FileActionEvent() + data class DeleteAllBookmark(val success: Boolean) : FileActionEvent() } \ No newline at end of file diff --git a/app/src/main/java/com/all/pdfreader/pro/app/room/dao/BookmarkDao.kt b/app/src/main/java/com/all/pdfreader/pro/app/room/dao/BookmarkDao.kt index e956641..d58b270 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/room/dao/BookmarkDao.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/room/dao/BookmarkDao.kt @@ -6,31 +6,31 @@ import kotlinx.coroutines.flow.Flow @Dao interface BookmarkDao { - + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(bookmark: BookmarkEntity): Long - + @Update - suspend fun update(bookmark: BookmarkEntity) - + suspend fun update(bookmark: BookmarkEntity): Int + @Delete - suspend fun delete(bookmark: BookmarkEntity) - + suspend fun delete(bookmark: BookmarkEntity): Int + @Query("SELECT * FROM bookmarks WHERE id = :bookmarkId") suspend fun getById(bookmarkId: Long): BookmarkEntity? - + @Query("SELECT * FROM bookmarks WHERE filePath = :filePath ORDER BY pageNumber ASC, createTime ASC") fun getBookmarksByPdf(filePath: String): Flow> - + @Query("SELECT * FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber") suspend fun getBookmarksByPage(filePath: String, pageNumber: Int): List - + @Query("SELECT COUNT(*) FROM bookmarks WHERE filePath = :filePath") suspend fun getBookmarkCount(filePath: String): Int - + @Query("DELETE FROM bookmarks WHERE filePath = :filePath") - suspend fun deleteAllByPdf(filePath: String) - + suspend fun deleteAllByPdf(filePath: String): Int + @Query("DELETE FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber") suspend fun deleteByPage(filePath: String, pageNumber: Int) } \ No newline at end of file diff --git a/app/src/main/java/com/all/pdfreader/pro/app/room/repository/PdfRepository.kt b/app/src/main/java/com/all/pdfreader/pro/app/room/repository/PdfRepository.kt index de3d475..236b4ed 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/room/repository/PdfRepository.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/room/repository/PdfRepository.kt @@ -39,12 +39,16 @@ class PdfRepository private constructor(context: Context) { fun searchDocuments(query: String): Flow> = pdfDao.searchDocuments(query) - suspend fun updateFilePathAndFileName(oldFilePath: String, newFilePath: String, newName: String) { + suspend fun updateFilePathAndFileName( + oldFilePath: String, + newFilePath: String, + newName: String + ) { pdfDao.updateFilePathAndFileName(oldFilePath, newFilePath, newName) } //语句更新可响应flow - suspend fun updateIsPassword(filePath: String, hasPassword: Boolean){ + suspend fun updateIsPassword(filePath: String, hasPassword: Boolean) { pdfDao.updateIsPassword(filePath, hasPassword) } @@ -105,8 +109,12 @@ class PdfRepository private constructor(context: Context) { // 书签相关操作 suspend fun addBookmark(bookmark: BookmarkEntity): Long = bookmarkDao.insert(bookmark) - suspend fun updateBookmark(bookmark: BookmarkEntity) = bookmarkDao.update(bookmark) - suspend fun deleteBookmark(bookmark: BookmarkEntity) = bookmarkDao.delete(bookmark) + suspend fun updateBookmark(bookmark: BookmarkEntity): Int = bookmarkDao.update(bookmark) + suspend fun deleteBookmark(bookmark: BookmarkEntity): Int = bookmarkDao.delete(bookmark) + suspend fun deleteAllBookmark(filePath: String): Int { + return bookmarkDao.deleteAllByPdf(filePath) + } + fun getBookmarksByPdf(filePath: String): Flow> = bookmarkDao.getBookmarksByPdf(filePath) diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt index c98197e..a7e12dd 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt @@ -3,20 +3,22 @@ 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 import com.all.pdfreader.pro.app.databinding.ActivityPdfViewBinding import com.all.pdfreader.pro.app.model.FileActionEvent import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity +import com.all.pdfreader.pro.app.ui.dialog.BookmarksDialogFragment import com.all.pdfreader.pro.app.ui.dialog.PdfPasswordProtectionDialogFragment import com.all.pdfreader.pro.app.ui.dialog.ViewModelDialogFragment import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle import com.all.pdfreader.pro.app.viewmodel.PdfViewModel import com.all.pdfreader.pro.app.viewmodel.observeEvent -import com.github.barteksc.pdfviewer.PDFView import com.github.barteksc.pdfviewer.listener.OnErrorListener import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener import com.github.barteksc.pdfviewer.listener.OnPageChangeListener @@ -58,6 +60,8 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList ?: throw IllegalArgumentException("PDF file hash is required") // 加载PDF数据 viewModel.getPDFDocument(filePath) + //加载书签数据 + viewModel.getBookmarks(filePath) } private fun initObserve() { @@ -73,12 +77,34 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList finish() } } + //观察书签数据 + viewModel.pdfBookmark.observe(this) { list -> + logDebug("observe->bookmarks: ${list.size}") + list?.let { + binding.bookmarksHint.text = "${it.size}" + if (it.isEmpty()) { + binding.bookmarksHint.visibility = View.GONE + } else { + binding.bookmarksHint.visibility = View.VISIBLE + } + } ?: run { + binding.bookmarksHint.visibility = View.GONE + } + } viewModel.fileActionEvent.observeEvent(this) { logDebug("observeEvent NoticeReload") val file = File(pdfDocument.filePath) loadPdfInternal(file, null) } + + viewModel.fileActionEvent.observeEvent(this) { + if (it.success) { + showToast(getString(R.string.bookmark_add_success)) + } else { + showToast(getString(R.string.bookmark_add_fail)) + } + } } private fun setupOnClick() { @@ -90,12 +116,15 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList toggleEyeCareMode(appStore.isEyeCareMode) } binding.viewModelBtn.setOnClickListener { - ViewModelDialogFragment(pdfDocument.filePath).show( - supportFragmentManager, "ViewModelDialogFragment" - ) + ViewModelDialogFragment().show(supportFragmentManager, "ViewModelDialogFragment") } binding.bookmarksBtn.setOnClickListener { - + BookmarksDialogFragment(pdfDocument, onJumpPage = { + binding.pdfview.jumpTo(it) + binding.pdfview.postDelayed({ + binding.pdfview.resetZoomWithAnimation() + }, 200) + }).show(supportFragmentManager, "BookmarksDialogFragment") } } diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/BookmarkAdapter.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/BookmarkAdapter.kt new file mode 100644 index 0000000..53357cf --- /dev/null +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/adapter/BookmarkAdapter.kt @@ -0,0 +1,66 @@ +package com.all.pdfreader.pro.app.ui.adapter + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.all.pdfreader.pro.app.databinding.AdapterItemBookmarkPageBinding +import com.all.pdfreader.pro.app.room.entity.BookmarkEntity + +class BookmarkAdapter( + private var list: MutableList, + private val onItemClick: (BookmarkEntity) -> Unit, + private val onEditClick: (BookmarkEntity) -> Unit, + private val onDeleteClick: (BookmarkEntity, Int) -> Unit, +) : RecyclerView.Adapter() { + + inner class PdfViewHolder(val binding: AdapterItemBookmarkPageBinding) : + RecyclerView.ViewHolder(binding.root) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PdfViewHolder { + val binding = AdapterItemBookmarkPageBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + return PdfViewHolder(binding) + } + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: PdfViewHolder, position: Int) { + val item = list[position] + holder.binding.titleTv.text = item.label + holder.binding.descTv.text = "(#${item.pageNumber + 1})" + holder.binding.root.setOnClickListener { + onItemClick(item) + } + holder.binding.editBtn.setOnClickListener { + onEditClick(item) + } + holder.binding.deleteBtn.setOnClickListener { + onDeleteClick(item, position) + } + } + + override fun getItemCount(): Int = list.size + + @SuppressLint("NotifyDataSetChanged") + fun updateData(newList: List) { + list.clear() + list.addAll(newList) + notifyDataSetChanged() + } + + fun removeItem(position: Int) { + list.removeAt(position) + notifyItemRemoved(position) + } + + fun removeAllItems() { + val size = list.size + if (size > 0) { + list.clear() + notifyItemRangeRemoved(0, size) + } + } +} diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/BookmarksDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/BookmarksDialogFragment.kt index b067d53..834a640 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/BookmarksDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/BookmarksDialogFragment.kt @@ -1,32 +1,31 @@ package com.all.pdfreader.pro.app.ui.dialog -import android.animation.ValueAnimator -import android.graphics.PorterDuff import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.animation.AccelerateDecelerateInterpolator -import android.widget.ImageView -import android.widget.TextView import android.widget.Toast 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.databinding.DialogViewModelBinding +import com.all.pdfreader.pro.app.room.entity.BookmarkEntity import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity -import com.all.pdfreader.pro.app.sp.AppStore -import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton -import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton.OnCheckedChangeListener +import com.all.pdfreader.pro.app.ui.adapter.BookmarkAdapter import com.all.pdfreader.pro.app.viewmodel.PdfViewModel import com.google.android.material.bottomsheet.BottomSheetDialogFragment -class BookmarksDialogFragment(val filePath: String) : BottomSheetDialogFragment() { +class BookmarksDialogFragment( + private val pdfDocument: PdfDocumentEntity, + private val onJumpPage: (Int) -> Unit +) : + BottomSheetDialogFragment() { private lateinit var binding: DialogBookmarksBinding private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel - private lateinit var pdfDocument: PdfDocumentEntity - private val appstore by lazy { AppStore(requireActivity()) } + private lateinit var bookmarks: List + private lateinit var adapter: BookmarkAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -55,21 +54,97 @@ class BookmarksDialogFragment(val filePath: String) : BottomSheetDialogFragment( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - viewModel.pdfDocument.value?.let { - pdfDocument = it - initUi() - setupOnClick() - } ?: run { + if (pdfDocument.filePath.isEmpty()) { showToast(getString(R.string.file_not)) dismiss() } + //观察书签数据 + viewModel.pdfBookmark.observe(this) { list -> + Log.d("ocean","BookmarksDialogFragment observe") + list?.let { + bookmarks = it + initView() + setupOnClick() + } + } + viewModel.getBookmarks(pdfDocument.filePath) } - private fun initUi() { + private fun initView() { + adapter = BookmarkAdapter(list = mutableListOf(), onItemClick = { bookmark -> + onJumpPage(bookmark.pageNumber) + dismiss() + }, onEditClick = { bookmark -> + + }, onDeleteClick = { bookmark, position -> + adapter.removeItem(position) + bookmarks = bookmarks.filter { it.id != bookmark.id } + viewModel.deleteBookMark(bookmark) + }) + binding.bookmarksPageRv.layoutManager = LinearLayoutManager(requireContext()) + binding.bookmarksPageRv.adapter = adapter + + if (bookmarks.isEmpty()) { + binding.noBookmarksPageLayout.visibility = View.VISIBLE//显示没有书签的提示布局 + binding.bookmarksDisplayLayout.visibility = View.GONE//隐藏显示内容的布局 + binding.addBtn.visibility = View.GONE//隐藏顶部的add按钮(因为布局noBookmarksPageLayout里面也会有一个add按钮) + } else { + binding.noBookmarksPageLayout.visibility = View.GONE + binding.bookmarksDisplayLayout.visibility = View.VISIBLE + binding.addBtn.visibility = View.VISIBLE + // 检查当前页是否已存在书签 + val alreadyBookmarked = bookmarks.any { it.pageNumber == pdfDocument.lastReadPage } + binding.addBtn.isEnabled = !alreadyBookmarked + if (alreadyBookmarked) { + binding.addTv.text = getString(R.string.added) + binding.addTv.setTextColor(requireActivity().getColor(R.color.grey_text_color)) + binding.addBtn.setBackgroundResource(R.drawable.dr_btn_not_clickable_bg) + binding.addIv.setImageResource(R.drawable.bookmark_icon_red) + } else { + binding.addTv.text = getString(R.string.add) + binding.addTv.setTextColor(requireActivity().getColor(R.color.white)) + binding.addBtn.setBackgroundResource(R.drawable.dr_click_btn_red_bg) + binding.addIv.setImageResource(R.drawable.add_icon_white) + } + + updateAdapter() + } } private fun setupOnClick() { + binding.addBookmarkBtn.setOnClickListener { + dialogAddBookMarks() + } + binding.addBtn.setOnClickListener { + dialogAddBookMarks() + } + binding.deleteALLPageBtn.setOnClickListener { + DeleteDialogFragment( + getString(R.string.delete_bookmarks_title), + getString(R.string.delete_bookmarks_desc), + onDeleteClick = { + viewModel.deleteAllBookmark(pdfDocument.filePath) + adapter.removeAllItems() + bookmarks = emptyList() + }).show(parentFragmentManager, "DeleteDialogFragment") + } + } + private fun dialogAddBookMarks() { + val bookmark = BookmarkEntity( + filePath = pdfDocument.filePath, + pageNumber = pdfDocument.lastReadPage, + label = getString(R.string.page) + "${pdfDocument.lastReadPage + 1}" + ) + viewModel.addBookMark(bookmark) + dismiss() + } + + private fun updateAdapter() { + if (bookmarks.isNotEmpty()) { + val sortedBookmarks = bookmarks.sortedByDescending { it.createTime } + adapter.updateData(sortedBookmarks) + } } private fun showToast(message: String) { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/DeleteDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/DeleteDialogFragment.kt index 86228a9..34bc5b4 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/DeleteDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/DeleteDialogFragment.kt @@ -8,17 +8,16 @@ import android.view.ViewGroup import android.widget.Toast import androidx.core.graphics.drawable.toDrawable import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.databinding.DialogDeleteBinding -import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity -import com.all.pdfreader.pro.app.viewmodel.PdfViewModel -class DeleteDialogFragment() : DialogFragment() { +class DeleteDialogFragment( + private val title: String, + private val desc: String, + private val onDeleteClick: () -> Unit +) : DialogFragment() { private lateinit var binding: DialogDeleteBinding - private val viewModel: PdfViewModel by activityViewModels() - private lateinit var pdfDocument: PdfDocumentEntity override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -42,18 +41,14 @@ class DeleteDialogFragment() : DialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - viewModel.pdfDocument.value?.let { - pdfDocument = it - setupOnClick() - } ?: run { - showToast(getString(R.string.file_not)) - dismiss() - } + binding.deleteTitleTv.text = title + binding.deleteDescTv.text = desc + setupOnClick() } private fun setupOnClick() { binding.okBtn.setOnClickListener { - viewModel.deleteFile(pdfDocument.filePath) + onDeleteClick() dismiss() } binding.cancelBtn.setOnClickListener { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt index 90abfae..2eb59b8 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt @@ -99,7 +99,12 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() dismiss() } binding.deleteFileBtn.setOnClickListener { - DeleteDialogFragment().show(parentFragmentManager, "DeleteDialogFragment") + DeleteDialogFragment( + getString(R.string.delete_file_title), + getString(R.string.delete_file_desc), + onDeleteClick = { + viewModel.deleteFile(pdfDocument.filePath) + }).show(parentFragmentManager, "DeleteDialogFragment") dismiss() } binding.detailsBtn.setOnClickListener { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt index 1d572d9..a111071 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt @@ -20,7 +20,7 @@ import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton.OnCheckedChangeListe import com.all.pdfreader.pro.app.viewmodel.PdfViewModel import com.google.android.material.bottomsheet.BottomSheetDialogFragment -class ViewModelDialogFragment(val filePath: String) : BottomSheetDialogFragment() { +class ViewModelDialogFragment() : BottomSheetDialogFragment() { private lateinit var binding: DialogViewModelBinding private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/view/CustomScrollHandle.java b/app/src/main/java/com/all/pdfreader/pro/app/ui/view/CustomScrollHandle.java index 386e036..0263c95 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/view/CustomScrollHandle.java +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/view/CustomScrollHandle.java @@ -18,8 +18,10 @@ import com.github.barteksc.pdfviewer.scroll.ScrollHandle; import com.github.barteksc.pdfviewer.util.Util; import androidx.core.content.ContextCompat; -import androidx.core.content.res.ResourcesCompat; +/** + * 重写了DefaultScrollHandle代码,添加动画效果,自定义background + */ public class CustomScrollHandle extends RelativeLayout implements ScrollHandle { private final static int HANDLE_LONG = 36; private final static int HANDLE_SHORT = 28; @@ -173,24 +175,28 @@ public class CustomScrollHandle extends RelativeLayout implements ScrollHandle { @Override public void show() { if (getVisibility() != VISIBLE) { - setTranslationX(getWidth()); // 初始在右侧外面 setAlpha(0f); + if (pdfView.isSwipeVertical()) { + setTranslationX(getWidth()); // 初始在右侧外面 + animate().translationX(0).alpha(1f).setDuration(450).start(); + } else { + setTranslationY(getHeight()); // 初始在底部外面 + animate().translationY(0).alpha(1f).setDuration(450).start(); + } setVisibility(VISIBLE); - animate().translationX(0) - .alpha(1f) - .setDuration(450) - .start(); } } @Override public void hide() { if (getVisibility() == VISIBLE) { - animate().translationX(getWidth()) // 滑到右边外面 - .alpha(0f) - .setDuration(450) - .withEndAction(() -> setVisibility(INVISIBLE)) - .start(); + if (pdfView.isSwipeVertical()) { + animate().translationX(getWidth()) // 滑到右边外面 + .alpha(0f).setDuration(450).withEndAction(() -> setVisibility(INVISIBLE)).start(); + } else { + animate().translationY(getHeight()) // 滑到下边外面 + .alpha(0f).setDuration(450).withEndAction(() -> setVisibility(INVISIBLE)).start(); + } } } @@ -208,7 +214,7 @@ public class CustomScrollHandle extends RelativeLayout implements ScrollHandle { /** * @param tf 自定义font字体 */ - public void setTypeface(Typeface tf){ + public void setTypeface(Typeface tf) { textView.setTypeface(tf); } diff --git a/app/src/main/java/com/all/pdfreader/pro/app/viewmodel/PdfViewModel.kt b/app/src/main/java/com/all/pdfreader/pro/app/viewmodel/PdfViewModel.kt index a063c9b..1575bd1 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/viewmodel/PdfViewModel.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/viewmodel/PdfViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.all.pdfreader.pro.app.PRApp import com.all.pdfreader.pro.app.model.FileActionEvent +import com.all.pdfreader.pro.app.room.entity.BookmarkEntity import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity import com.all.pdfreader.pro.app.room.repository.PdfRepository import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail @@ -120,8 +121,7 @@ class PdfViewModel : ViewModel() { val newThumbnail = generateFastThumbnail(context, file) if (newThumbnail != null && document.thumbnailPath != newThumbnail) { pdfRepository.updateThumbnailPath( - document.filePath, - newThumbnail + document.filePath, newThumbnail ) Log.d("ocean", "✅ 缩略图已更新") } @@ -146,8 +146,7 @@ class PdfViewModel : ViewModel() { } _fileActionEvent.postValue( FileActionEvent.SetPassword( - FileActionEvent.SetPassword.Status.COMPLETE, - success + FileActionEvent.SetPassword.Status.COMPLETE, success ) ) } @@ -165,7 +164,8 @@ class PdfViewModel : ViewModel() { pdfRepository.updateIsPassword(filePath, false) val document = pdfRepository.getDocumentByPath(filePath) if (document?.thumbnailPath.isNullOrEmpty()) { - val newThumbnail = generateFastThumbnail(PRApp.getContext(), File(filePath)) + val newThumbnail = + generateFastThumbnail(PRApp.getContext(), File(filePath)) Log.d("ocean", "最新图片:$newThumbnail") if (!newThumbnail.isNullOrEmpty() && filePath != newThumbnail) { pdfRepository.updateThumbnailPath(filePath, newThumbnail) @@ -181,8 +181,7 @@ class PdfViewModel : ViewModel() { _fileActionEvent.postValue( FileActionEvent.RemovePassword( - FileActionEvent.RemovePassword.Status.COMPLETE, - success + FileActionEvent.RemovePassword.Status.COMPLETE, success ) ) } @@ -193,4 +192,44 @@ class PdfViewModel : ViewModel() { _fileActionEvent.postValue(FileActionEvent.NoticeReload) } } + + /** + * 书签相关方法 + */ + private val _pdfBookmark = MutableLiveData>() + val pdfBookmark: LiveData> = _pdfBookmark + + fun getBookmarks(filePath: String) { + viewModelScope.launch { + Log.d("ocean", "getBookmarks->filePath: $filePath") + pdfRepository.getBookmarksByPdf(filePath).collect { bookmarks -> + _pdfBookmark.value = bookmarks + } + } + } + + fun addBookMark(bookmark: BookmarkEntity) { + viewModelScope.launch { + Log.d("ocean", "addBookMarks->bookmark: $bookmark") + val id = pdfRepository.addBookmark(bookmark) + val success = id != -1L//插入成功,会返回 新生成的主键 id + _fileActionEvent.postValue(FileActionEvent.AddBookmark(success)) + } + } + + fun deleteBookMark(bookmark: BookmarkEntity) { + viewModelScope.launch { + val int = pdfRepository.deleteBookmark(bookmark) + val success = int > 0//受影响行数大于0 + _fileActionEvent.postValue(FileActionEvent.DeleteBookmark(success)) + } + } + + fun deleteAllBookmark(filePath: String) { + viewModelScope.launch { + val int = pdfRepository.deleteAllBookmark(filePath) + val success = int > 0 + _fileActionEvent.postValue(FileActionEvent.DeleteAllBookmark(success)) + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/add_bookmarks_white.xml b/app/src/main/res/drawable/add_bookmarks_white.xml new file mode 100644 index 0000000..e7371a6 --- /dev/null +++ b/app/src/main/res/drawable/add_bookmarks_white.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/add_icon_grey.xml b/app/src/main/res/drawable/add_icon_grey.xml new file mode 100644 index 0000000..461c604 --- /dev/null +++ b/app/src/main/res/drawable/add_icon_grey.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/add_icon_white.xml b/app/src/main/res/drawable/add_icon_white.xml new file mode 100644 index 0000000..6d6e4ab --- /dev/null +++ b/app/src/main/res/drawable/add_icon_white.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/bookmark_icon_red.xml b/app/src/main/res/drawable/bookmark_icon_red.xml new file mode 100644 index 0000000..fd6d6fa --- /dev/null +++ b/app/src/main/res/drawable/bookmark_icon_red.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/drawable/delete_cha_icon.xml b/app/src/main/res/drawable/delete_cha_icon.xml new file mode 100644 index 0000000..c2064e5 --- /dev/null +++ b/app/src/main/res/drawable/delete_cha_icon.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/dr_bookmarks_bg.xml b/app/src/main/res/drawable/dr_bookmarks_bg.xml new file mode 100644 index 0000000..9829eae --- /dev/null +++ b/app/src/main/res/drawable/dr_bookmarks_bg.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dr_btn_not_clickable_bg.xml b/app/src/main/res/drawable/dr_btn_not_clickable_bg.xml new file mode 100644 index 0000000..6061c58 --- /dev/null +++ b/app/src/main/res/drawable/dr_btn_not_clickable_bg.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/dr_click_btn_bg.xml b/app/src/main/res/drawable/dr_click_btn_bg.xml index 8ff4b23..fd05e1f 100644 --- a/app/src/main/res/drawable/dr_click_btn_bg.xml +++ b/app/src/main/res/drawable/dr_click_btn_bg.xml @@ -5,7 +5,7 @@ - + @@ -13,7 +13,7 @@ - + diff --git a/app/src/main/res/drawable/dr_click_btn_red_bg.xml b/app/src/main/res/drawable/dr_click_btn_red_bg.xml index d0d2f29..99d7fb1 100644 --- a/app/src/main/res/drawable/dr_click_btn_red_bg.xml +++ b/app/src/main/res/drawable/dr_click_btn_red_bg.xml @@ -5,7 +5,7 @@ - + @@ -13,7 +13,7 @@ - + diff --git a/app/src/main/res/drawable/dr_dot_red.xml b/app/src/main/res/drawable/dr_dot_red.xml new file mode 100644 index 0000000..abc1a8d --- /dev/null +++ b/app/src/main/res/drawable/dr_dot_red.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dr_item_bookmark_page_bg.xml b/app/src/main/res/drawable/dr_item_bookmark_page_bg.xml new file mode 100644 index 0000000..cf7511f --- /dev/null +++ b/app/src/main/res/drawable/dr_item_bookmark_page_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/edit_icon.xml b/app/src/main/res/drawable/edit_icon.xml new file mode 100644 index 0000000..aff1bb1 --- /dev/null +++ b/app/src/main/res/drawable/edit_icon.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/page_icon.xml b/app/src/main/res/drawable/page_icon.xml new file mode 100644 index 0000000..ae3fceb --- /dev/null +++ b/app/src/main/res/drawable/page_icon.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0f007b9..ea33070 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -113,18 +113,18 @@ android:orientation="vertical"> @@ -197,9 +198,10 @@ @@ -221,9 +223,10 @@ @@ -245,9 +248,10 @@ diff --git a/app/src/main/res/layout/activity_pdf_view.xml b/app/src/main/res/layout/activity_pdf_view.xml index da3dbbc..01c88de 100644 --- a/app/src/main/res/layout/activity_pdf_view.xml +++ b/app/src/main/res/layout/activity_pdf_view.xml @@ -77,19 +77,20 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:gravity="center_horizontal|bottom" + android:gravity="center" android:orientation="vertical"> @@ -101,20 +102,21 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:gravity="center_horizontal|bottom" + android:gravity="center" android:orientation="vertical"> @@ -125,19 +127,41 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:gravity="center_horizontal|bottom" + android:gravity="center" android:orientation="vertical"> - + + + + + + + @@ -148,19 +172,20 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:gravity="center_horizontal|bottom" + android:gravity="center" android:orientation="vertical"> diff --git a/app/src/main/res/layout/adapter_item_bookmark_page.xml b/app/src/main/res/layout/adapter_item_bookmark_page.xml new file mode 100644 index 0000000..f26b8d8 --- /dev/null +++ b/app/src/main/res/layout/adapter_item_bookmark_page.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_bookmarks.xml b/app/src/main/res/layout/dialog_bookmarks.xml index 6f603f2..3e4bde1 100644 --- a/app/src/main/res/layout/dialog_bookmarks.xml +++ b/app/src/main/res/layout/dialog_bookmarks.xml @@ -1,10 +1,11 @@ + android:fitsSystemWindows="true" + android:orientation="vertical"> - + + + + + + + + + + + + + + + + android:gravity="center" + android:orientation="vertical" + android:visibility="visible"> + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_delete.xml b/app/src/main/res/layout/dialog_delete.xml index b0292a7..ba016a6 100644 --- a/app/src/main/res/layout/dialog_delete.xml +++ b/app/src/main/res/layout/dialog_delete.xml @@ -6,22 +6,24 @@ android:orientation="vertical"> @@ -41,9 +43,9 @@ android:gravity="center"> @@ -59,9 +61,9 @@ android:gravity="center"> diff --git a/app/src/main/res/layout/dialog_permission.xml b/app/src/main/res/layout/dialog_permission.xml index 27640eb..7f0d54e 100644 --- a/app/src/main/res/layout/dialog_permission.xml +++ b/app/src/main/res/layout/dialog_permission.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" + android:fitsSystemWindows="true" android:orientation="vertical" android:padding="16dp" tools:ignore="UseCompoundDrawables"> @@ -36,10 +37,10 @@ tools:ignore="ContentDescription" /> diff --git a/app/src/main/res/layout/dialog_sort.xml b/app/src/main/res/layout/dialog_sort.xml index 12f306c..0f6670d 100644 --- a/app/src/main/res/layout/dialog_sort.xml +++ b/app/src/main/res/layout/dialog_sort.xml @@ -2,6 +2,7 @@ #666666 #80FFD699 #636366 + #F1494F \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2139ca4..3f5dd6d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,6 +29,8 @@ Unlock Eye Protect Bookmarks + No Bookmarks Page + You haven\'t added any page to your bookmarks.Please add pages to see them here. Set PDF Password Set a protection password for the PDF file, Leaving it blank means no password is set. PDF Password Protection @@ -45,9 +47,13 @@ Share Print Added to Favorite + Add Bookmark + Added + Add Removed from Favorites Delete File Delete + Delete All Pages Set Password Set Password successfully Set Password failed @@ -101,4 +107,10 @@ color inversion Horizontal Vertical + Page + Bookmark added successfully + Failed to add bookmark + Bookmark remove + Delete Bookmarks + Are you sure you want to delete all Bookmarks? \ No newline at end of file