添加解密工具。优化结果页面。
This commit is contained in:
parent
43ece1be95
commit
b04a8c9142
@ -15,6 +15,7 @@ import com.all.pdfreader.pro.app.model.SortConfig
|
||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||
import com.all.pdfreader.pro.app.ui.adapter.PdfAdapter
|
||||
import com.all.pdfreader.pro.app.ui.dialog.PdfRemovePasswordDialog
|
||||
import com.all.pdfreader.pro.app.ui.dialog.PdfSetPasswordDialog
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.setOnSingleClickListener
|
||||
@ -93,7 +94,14 @@ class PdfPickerActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
PdfPickerSource.UNLOCK -> {
|
||||
|
||||
PdfRemovePasswordDialog(pdf.filePath, onOkClick = { password ->
|
||||
val intent = PdfResultActivity.createIntentLock(
|
||||
this, pdf.filePath, password,
|
||||
PdfPickerSource.UNLOCK
|
||||
)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}).show(supportFragmentManager, "PdfRemovePasswordDialog")
|
||||
}
|
||||
|
||||
PdfPickerSource.TO_IMAGES -> {}
|
||||
|
||||
@ -15,10 +15,10 @@ import com.all.pdfreader.pro.app.databinding.ActivityPdfSplitResultBinding
|
||||
import com.all.pdfreader.pro.app.model.PdfPickerSource
|
||||
import com.all.pdfreader.pro.app.model.PdfSelectedPagesItem
|
||||
import com.all.pdfreader.pro.app.model.PdfSplitResultItem
|
||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||
import com.all.pdfreader.pro.app.ui.adapter.PdfResultAdapter
|
||||
import com.all.pdfreader.pro.app.ui.dialog.PromptDialogFragment
|
||||
import com.all.pdfreader.pro.app.util.AppUtils
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail
|
||||
import com.all.pdfreader.pro.app.util.FileUtils.toUnderscoreDateTime
|
||||
import com.all.pdfreader.pro.app.util.PdfScanner
|
||||
import com.all.pdfreader.pro.app.util.PdfSecurityUtils
|
||||
@ -111,7 +111,7 @@ class PdfResultActivity : BaseActivity() {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
} else if (source == PdfPickerSource.LOCK) {
|
||||
} else if (source == PdfPickerSource.LOCK || source == PdfPickerSource.UNLOCK) {
|
||||
if (filepath.isEmpty() || password.isEmpty()) {
|
||||
showToast(getString(R.string.pdf_loading_failed))
|
||||
finish()
|
||||
@ -166,8 +166,7 @@ class PdfResultActivity : BaseActivity() {
|
||||
binding.progressBar.progress = percent
|
||||
}
|
||||
})?.let { resultFile ->
|
||||
val thumbnails =
|
||||
AppUtils.generateFastThumbnail(this@PdfResultActivity, resultFile)
|
||||
val thumbnails = generateFastThumbnail(this@PdfResultActivity, resultFile)
|
||||
val result = PdfSplitResultItem(resultFile.absolutePath, thumbnails, false)
|
||||
pdfScanner.addNewPdfToDatabase(result.filePath, result.thumbnailPath) {
|
||||
resultList.add(result)
|
||||
@ -198,8 +197,7 @@ class PdfResultActivity : BaseActivity() {
|
||||
binding.progressTv.text = "$progressPercent"
|
||||
}
|
||||
})?.let { resultFile ->
|
||||
val thumbnails =
|
||||
AppUtils.generateFastThumbnail(this@PdfResultActivity, resultFile)
|
||||
val thumbnails = generateFastThumbnail(this@PdfResultActivity, resultFile)
|
||||
val result = PdfSplitResultItem(resultFile.absolutePath, thumbnails, false)
|
||||
pdfScanner.addNewPdfToDatabase(result.filePath, result.thumbnailPath) {
|
||||
resultList.add(result)
|
||||
@ -214,11 +212,23 @@ class PdfResultActivity : BaseActivity() {
|
||||
binding.progressTv.text = "$progress"
|
||||
}.let { it ->
|
||||
if (it) {
|
||||
PdfRepository.getInstance().updateIsPassword(filepath, true)
|
||||
pdfRepository.updateIsPassword(filepath, true)
|
||||
}
|
||||
val result = PdfSplitResultItem(filePath = filepath, isPassword = true)
|
||||
resultList.add(result)
|
||||
}
|
||||
} else if (source == PdfPickerSource.UNLOCK) {
|
||||
binding.congratulationsDesc.text = getString(R.string.remove_password_successfully)
|
||||
PdfSecurityUtils.removePasswordFromPdfWithProgress(filepath, password) { progress ->
|
||||
binding.progressTv.text = "$progress"
|
||||
}?.let { it ->
|
||||
val result = PdfSplitResultItem(
|
||||
filePath = filepath,
|
||||
thumbnailPath = it,
|
||||
isPassword = false
|
||||
)
|
||||
resultList.add(result)
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.processingLayout.visibility = View.GONE
|
||||
@ -227,7 +237,7 @@ class PdfResultActivity : BaseActivity() {
|
||||
resultList[0].isSelected = true
|
||||
}
|
||||
adapter.updateAdapter()
|
||||
isProcessing = false//拆分结束
|
||||
isProcessing = false
|
||||
exitDialog?.dismissAllowingStateLoss()
|
||||
exitDialog = null
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.all.pdfreader.pro.app.ui.dialog
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -195,7 +194,9 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
|
||||
}
|
||||
binding.setPasswordBtn.setOnClickListener {
|
||||
if (pdfDocument.isPassword) {
|
||||
PdfRemovePasswordDialog().show(parentFragmentManager, "PdfRemovePasswordDialog")
|
||||
PdfRemovePasswordDialog(pdfDocument.filePath, onOkClick = { password ->
|
||||
viewModel.removePassword(pdfDocument.filePath, password)
|
||||
}).show(parentFragmentManager, "PdfRemovePasswordDialog")
|
||||
} else {
|
||||
PdfSetPasswordDialog(onOkClick = { password ->
|
||||
viewModel.setPassword(pdfDocument.filePath, password)
|
||||
|
||||
@ -7,22 +7,19 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
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.DialogPdfRemovePasswordBinding
|
||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
|
||||
import com.all.pdfreader.pro.app.util.FileUtils.isPdfPasswordCorrect
|
||||
import com.all.pdfreader.pro.app.util.ToastUtils
|
||||
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||
import java.io.File
|
||||
|
||||
class PdfRemovePasswordDialog() : DialogFragment(
|
||||
|
||||
) {
|
||||
class PdfRemovePasswordDialog(
|
||||
val filePath: String,
|
||||
val onOkClick: (password: String) -> Unit = {}
|
||||
) :
|
||||
DialogFragment() {
|
||||
private lateinit var binding: DialogPdfRemovePasswordBinding
|
||||
private val viewModel: PdfViewModel by activityViewModels()
|
||||
private lateinit var pdfDocument: PdfDocumentEntity
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
@ -46,14 +43,8 @@ class PdfRemovePasswordDialog() : DialogFragment(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
viewModel.pdfDocument.value?.let {
|
||||
pdfDocument = it
|
||||
binding.etPassword.showKeyboard()
|
||||
setupListeners()
|
||||
} ?: run {
|
||||
showToast(getString(R.string.file_not))
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
@ -63,8 +54,8 @@ class PdfRemovePasswordDialog() : DialogFragment(
|
||||
|
||||
binding.tvConfirm.setOnClickListener {
|
||||
val password = binding.etPassword.text.toString()
|
||||
if (isPdfPasswordCorrect(requireActivity(), File(pdfDocument.filePath), password)) {
|
||||
viewModel.removePassword(pdfDocument.filePath, password)
|
||||
if (isPdfPasswordCorrect(requireActivity(), File(filePath), password)) {
|
||||
onOkClick(password)
|
||||
dismiss()
|
||||
} else {
|
||||
binding.tilPassword.error = getString(R.string.incorrect_password)
|
||||
|
||||
@ -37,5 +37,9 @@ class ToolsFrag : Fragment() {
|
||||
val intent = PdfPickerActivity.createIntent(requireActivity(), PdfPickerSource.LOCK)
|
||||
startActivity(intent)
|
||||
}
|
||||
binding.unLockBtn.setOnClickListener {
|
||||
val intent = PdfPickerActivity.createIntent(requireActivity(), PdfPickerSource.UNLOCK)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
package com.all.pdfreader.pro.app.util
|
||||
|
||||
import android.graphics.pdf.PdfDocument
|
||||
import com.all.pdfreader.pro.app.PRApp
|
||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail
|
||||
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
||||
import com.tom_roush.pdfbox.pdmodel.encryption.AccessPermission
|
||||
import com.tom_roush.pdfbox.pdmodel.encryption.StandardProtectionPolicy
|
||||
@ -45,7 +48,6 @@ object PdfSecurityUtils {
|
||||
val job = launch {
|
||||
while (isActive && progress < 98) {
|
||||
delay(50)
|
||||
// 专业曲线:前 80%慢,后 20%快
|
||||
progress += when {
|
||||
progress < 80 -> 1 // 前 80% 每次 +1
|
||||
progress < 90 -> 2 // 80~90% 每次 +2
|
||||
@ -63,9 +65,17 @@ object PdfSecurityUtils {
|
||||
// 停止假进度
|
||||
job.cancel()
|
||||
|
||||
// 最终完成直接 100%
|
||||
// 最后 98 -> 100 有一个 1 秒左右的平滑视觉过渡
|
||||
val finalStart = progress
|
||||
val finalEnd = 100
|
||||
val steps = (finalEnd - finalStart).coerceAtLeast(2) // 至少两步
|
||||
val delayPerStep = 1000L / steps
|
||||
|
||||
for (p in finalStart..finalEnd) {
|
||||
withContext(Dispatchers.Main) {
|
||||
onProgress(100)
|
||||
onProgress(p)
|
||||
}
|
||||
delay(delayPerStep)
|
||||
}
|
||||
success
|
||||
}
|
||||
@ -84,4 +94,61 @@ object PdfSecurityUtils {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun removePasswordFromPdfWithProgress(
|
||||
inputFilePath: String,
|
||||
password: String,
|
||||
onProgress: (Int) -> Unit
|
||||
): String? = withContext(Dispatchers.IO) {
|
||||
var newThumbnail: String? = null
|
||||
var success = false
|
||||
var progress = 0
|
||||
|
||||
// 启动假进度
|
||||
val job = launch {
|
||||
while (isActive && progress < 98) {
|
||||
delay(50)
|
||||
progress += when {
|
||||
progress < 80 -> 1 // 前 80% 每次 +1
|
||||
progress < 90 -> 2 // 80~90% 每次 +2
|
||||
else -> 3 // 90~98% 每次 +3
|
||||
}
|
||||
if (progress > 98) progress = 98
|
||||
withContext(Dispatchers.Main) {
|
||||
onProgress(progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行移除密码操作
|
||||
success = removePasswordFromPdf(inputFilePath, password)
|
||||
if (success) {
|
||||
val pdfRepository = PdfRepository.getInstance()
|
||||
pdfRepository.updateIsPassword(inputFilePath, false)
|
||||
newThumbnail = generateFastThumbnail(PRApp.getContext(), File(inputFilePath))
|
||||
val document = pdfRepository.getDocumentByPath(inputFilePath)
|
||||
if (document?.thumbnailPath.isNullOrEmpty()) {
|
||||
if (!newThumbnail.isNullOrEmpty() && inputFilePath != newThumbnail) {
|
||||
pdfRepository.updateThumbnailPath(inputFilePath, newThumbnail)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 停止假进度
|
||||
job.cancel()
|
||||
|
||||
// 最后 98 -> 100 平滑过渡 1 秒
|
||||
val finalStart = progress
|
||||
val finalEnd = 100
|
||||
val steps = (finalEnd - finalStart).coerceAtLeast(2)
|
||||
val delayPerStep = 1000L / steps
|
||||
|
||||
for (p in finalStart..finalEnd) {
|
||||
withContext(Dispatchers.Main) {
|
||||
onProgress(p)
|
||||
}
|
||||
delay(delayPerStep)
|
||||
}
|
||||
|
||||
newThumbnail
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user