diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 02dfa57..65ac6bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,9 @@ android:supportsRtl="true" android:theme="@style/Theme.FileRecovery" tools:targetApi="31"> + @@ -39,6 +42,9 @@ + diff --git a/app/src/main/java/com/ux/video/file/filerecovery/base/BaseIngDialogFragment.kt b/app/src/main/java/com/ux/video/file/filerecovery/base/BaseIngDialogFragment.kt new file mode 100644 index 0000000..8fa73dd --- /dev/null +++ b/app/src/main/java/com/ux/video/file/filerecovery/base/BaseIngDialogFragment.kt @@ -0,0 +1,83 @@ +package com.ux.video.file.filerecovery.base + +import android.annotation.SuppressLint +import android.graphics.Color +import android.os.Bundle +import android.os.CountDownTimer +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.graphics.drawable.toDrawable +import androidx.fragment.app.DialogFragment +import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding + + +abstract class BaseIngDialogFragment(var total: Int, var complete: () -> Unit) : DialogFragment() { + + private lateinit var binding: DialogRecoveringBinding + + + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setLayout( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + setGravity(Gravity.BOTTOM) + setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = DialogRecoveringBinding.inflate(inflater) + initUi(binding) + binding.run { + if (total < 20) { + val defaultTimer = 2000L + object : CountDownTimer(defaultTimer, 200) { + override fun onFinish() { + progressBar.progress = 100 + complete.invoke() + } + + override fun onTick(millisUntilFinished: Long) { + var progressPercentage = ((100 * millisUntilFinished) / defaultTimer) + val i = (100 - progressPercentage).toInt() + progressBar.progress = i + } + + }.start() + } + } + + + return binding.root + } + + protected abstract fun initUi(binding: DialogRecoveringBinding) + + @SuppressLint("SetTextI18n") + fun updateProgress(number: Int) { + binding.tvRecoverNumber.text = "${number}/" + if (total < 20) { + return + } + val progress = if (total > 20) { + (number * 100f / total).toInt() + } else { + 0 + } + binding.progressBar.progress = progress + + if (progress == 100) { + complete.invoke() + } + } + + +} diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/DatePickerDialogFragment.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/DatePickerDialogFragment.kt index 79d0c6d..63352fb 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/photo/DatePickerDialogFragment.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/DatePickerDialogFragment.kt @@ -42,27 +42,5 @@ class DatePickerDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFra return binding.root } - fun showDatePicker() { - // 创建日期选择器构建器 - val builder = MaterialDatePicker.Builder.datePicker() - builder.setTitleText("选择日期") - // 可选:限制可选日期,比如只能选择今天之后的日期 - val constraintsBuilder = CalendarConstraints.Builder() - constraintsBuilder.setValidator(DateValidatorPointForward.now()) // 今天之后 - builder.setCalendarConstraints(constraintsBuilder.build()) - - val datePicker = builder.build() - - // 显示日期选择器 -// datePicker.show(supportFragmentManager, "MATERIAL_DATE_PICKER") - - // 监听用户选择 - datePicker.addOnPositiveButtonClickListener { selection -> - // selection 是 Long 类型的时间戳(UTC 毫秒) - val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) - val dateString = sdf.format(Date(selection)) - println("用户选择的日期:$dateString") - } - } } diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/DeletingDialogFragment.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/DeletingDialogFragment.kt new file mode 100644 index 0000000..67c2305 --- /dev/null +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/DeletingDialogFragment.kt @@ -0,0 +1,24 @@ +package com.ux.video.file.filerecovery.photo + +import com.ux.video.file.filerecovery.R +import com.ux.video.file.filerecovery.base.BaseIngDialogFragment +import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding + + +/** + * 删除中弹窗 + */ +class DeletingDialogFragment(total: Int, complete:()-> Unit) : BaseIngDialogFragment(total,complete) { + + override fun initUi(binding: DialogRecoveringBinding) { + binding.run { + relativeLayout.setBackgroundResource(R.drawable.bg_rectangle_fdad00_top_20) + tvType.text = getString(R.string.deleting) + tvContent.text = getString(R.string.delete_content) + tvTotal.text = total.toString() + } + } + + + +} diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateAdapter.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateAdapter.kt index c5b542b..45abf11 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateAdapter.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateAdapter.kt @@ -8,7 +8,6 @@ import androidx.recyclerview.widget.GridLayoutManager import com.ux.video.file.filerecovery.base.BaseAdapter import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding import com.ux.video.file.filerecovery.utils.Common -import com.ux.video.file.filerecovery.utils.ExtendFunctions.resetItemDecorationOnce import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration import com.ux.video.file.filerecovery.utils.ScanRepository @@ -16,7 +15,8 @@ class PhotoDisplayDateAdapter( mContext: Context, var mColumns: Int, var viewModel: ScanRepository, - var onSelectedUpdate: (updatePath: String, isAdd: Boolean) -> Unit + var onSelectedUpdate: (updatePath: String, isAdd: Boolean) -> Unit, + var clickItem:(item:ResultPhotosFiles)-> Unit ) : BaseAdapter>, PhotoDisplayDateAdapterBinding>(mContext) { @@ -46,6 +46,7 @@ class PhotoDisplayDateAdapter( } } notifyDataSetChanged() + allSelected = null } fun resetAllValue(b: Boolean?){ @@ -72,12 +73,12 @@ class PhotoDisplayDateAdapter( val childAdapter = PhotoDisplayDateChildAdapter( mContext, mColumns, - viewModel - ) { path, addOrRemove, isDateAllSelected -> + viewModel, + { path, addOrRemove, isDateAllSelected -> //点击当前Adapter某一天的全选或者子Item上的选中都会回调到这里 tvDayAllSelect.isSelected = isDateAllSelected onSelectedUpdate(path.toString(),addOrRemove) - }.apply { setData(files) } + },clickItem).apply { setData(files) } allSelected?.let { childAdapter.setAllSelected(it) diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateChildAdapter.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateChildAdapter.kt index 7ee9c0b..85f8d02 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateChildAdapter.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoDisplayDateChildAdapter.kt @@ -36,7 +36,8 @@ class PhotoDisplayDateChildAdapter( * @param addOrRemove 选中还是取消选中 * @param dateAllSelected 这组数据是否全部选中(某一天) */ - var onSelectedUpdate: (updatePath: String, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit + var onSelectedUpdate: (updatePath: String, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit, + var clickItem:(item:ResultPhotosFiles)-> Unit ) : NewBaseAdapter(mContext) { @@ -189,6 +190,7 @@ class PhotoDisplayDateChildAdapter( }) .into(imageThumbnail) + rootLayout.setOnClickListener { clickItem(item) } setHeight(rootLayout) } diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoInfoActivity.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoInfoActivity.kt new file mode 100644 index 0000000..88d31cb --- /dev/null +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoInfoActivity.kt @@ -0,0 +1,92 @@ +package com.ux.video.file.filerecovery.photo + +import android.graphics.drawable.Drawable +import android.os.Build +import android.os.Bundle +import android.view.LayoutInflater +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.bitmap.CenterCrop +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target +import com.ux.video.file.filerecovery.R +import com.ux.video.file.filerecovery.base.BaseActivity +import com.ux.video.file.filerecovery.databinding.ActivityPhotoInfoBinding +import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding +import com.ux.video.file.filerecovery.utils.Common +import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx +import com.ux.video.file.filerecovery.utils.ScanManager + +class PhotoInfoActivity : BaseActivity() { + + companion object { + val KEY_CLICK_ITEM = "click_item" + } + + private var myData: ResultPhotosFiles? = null + + override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding = + ActivityPhotoInfoBinding.inflate(inflater) + + override fun initView() { + super.initView() + myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getParcelableExtra(KEY_CLICK_ITEM, ResultPhotosFiles::class.java) + } else { + @Suppress("DEPRECATION") + intent.getParcelableExtra("MY_KEY") + } + + binding.run { + myData?.let { + + tvName.text = it.name + tvPath.text = it.path + tvDate.text = Common.getFormatDate(it.lastModified) + tvResolution.text = it.resolution + + Glide.with(this@PhotoInfoActivity) + .load(it.targetFile) + .apply( + RequestOptions() + .transform( + CenterCrop(), + RoundedCorners(8.dpToPx(this@PhotoInfoActivity)) + ) + ) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: com.bumptech.glide.request.target.Target, + isFirstResource: Boolean + ): Boolean { + return false + } + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target?, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + + return false + } + + }) + .into(image) + } + } + + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoSortingActivity.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoSortingActivity.kt index f0a3d62..7b5a8f2 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoSortingActivity.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/PhotoSortingActivity.kt @@ -1,5 +1,6 @@ package com.ux.video.file.filerecovery.photo +import android.content.Intent import android.view.LayoutInflater import android.widget.LinearLayout import androidx.activity.viewModels @@ -9,9 +10,13 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.datepicker.CalendarConstraints +import com.google.android.material.datepicker.DateValidatorPointForward +import com.google.android.material.datepicker.MaterialDatePicker import com.ux.video.file.filerecovery.R import com.ux.video.file.filerecovery.base.BaseActivity import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding +import com.ux.video.file.filerecovery.success.RecoverySuccessActivity import com.ux.video.file.filerecovery.utils.Common import com.ux.video.file.filerecovery.utils.Common.setItemSelect import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx @@ -28,6 +33,9 @@ import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync import com.ux.video.file.filerecovery.utils.ScanManager.deleteFilesAsync import com.ux.video.file.filerecovery.utils.ScanRepository import kotlinx.coroutines.launch +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale class PhotoSortingActivity : BaseActivity() { @@ -58,6 +66,10 @@ class PhotoSortingActivity : BaseActivity() { //文件大小排序使用的适配器 private var sizeSortAdapter: PhotoDisplayDateChildAdapter? = null + private var dialogRecovering: RecoveringDialogFragment? = null + + private var dialogDeleting: DeletingDialogFragment? = null + //默认倒序排序 private var sortReverse = true @@ -112,6 +124,7 @@ class PhotoSortingActivity : BaseActivity() { Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}") updateCurrentIsAllSelectStatus() } + binding.imageViewBack.setOnClickListener { finish() } list?.let { //降序(最近的在前面) @@ -123,21 +136,34 @@ class PhotoSortingActivity : BaseActivity() { sizeSortAdapter = PhotoDisplayDateChildAdapter( this@PhotoSortingActivity, - columns, viewModel - ) { path, isAdd, allSelected -> -// updateSelectedList(isAdd, path) -// updateCurrentIsAllSelectStatus() - viewModel.toggleSelection(isAdd, path) + columns, viewModel, + { path, isAdd, allSelected -> + viewModel.toggleSelection(isAdd, path) + }) { item -> + startActivity( + Intent( + this@PhotoSortingActivity, + PhotoInfoActivity::class.java + ).apply { + putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item) + }) + } dateAdapter = PhotoDisplayDateAdapter( this@PhotoSortingActivity, columns, - viewModel - ) { actionPath, isAdd -> -// updateSelectedList(isAdd, actionPath) -// updateCurrentIsAllSelectStatus() - viewModel.toggleSelection(isAdd, actionPath) + viewModel, + { actionPath, isAdd -> + viewModel.toggleSelection(isAdd, actionPath) + }) { item -> + startActivity( + Intent( + this@PhotoSortingActivity, + PhotoInfoActivity::class.java + ).apply { + putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item) + }) }.apply { setData(sortByDateReverse) } @@ -145,23 +171,25 @@ class PhotoSortingActivity : BaseActivity() { setFilter() binding.run { tvRecover.setOnClickListener { + showRecoveringDialog() lifecycleScope.copySelectedFilesAsync( selectedSet = filterSelectedSetList, folder = Common.recoveryPhotoDir, onProgress = { currentCounts: Int, fileName: String, success: Boolean -> - ScanManager.showLog( "--------恢复图片 ", "----------${currentCounts} ${fileName}" ) + dialogRecovering?.updateProgress(currentCounts) }) { counts -> - + dialogRecovering?.updateProgress(counts) ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}") } } tvDelete.setOnClickListener { + showDeletingDialog() lifecycleScope.deleteFilesAsync( selectedSet = filterSelectedSetList, onProgress = { currentCounts: Int, path: String, success: Boolean -> @@ -169,9 +197,9 @@ class PhotoSortingActivity : BaseActivity() { "--------删除图片 ", "----------${currentCounts} ${path}" ) - + dialogDeleting?.updateProgress(currentCounts) }) { counts -> - + dialogDeleting?.updateProgress(counts) ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}") } @@ -240,9 +268,9 @@ class PhotoSortingActivity : BaseActivity() { binding.recyclerView.run { adapter = dateAdapter?.apply { setColumns(columns) } layoutManager = LinearLayoutManager(this@PhotoSortingActivity) - val bPx = 16.dpToPx(context) - setPadding(0, 0, 0, 0) - clipToPadding = false + val bPx = 16.dpToPx(context) + setPadding(0, 0, 0, 0) + clipToPadding = false } @@ -281,7 +309,7 @@ class PhotoSortingActivity : BaseActivity() { data[1] -> filterDate = FILTER_DATE_1 data[2] -> filterDate = FILTER_DATE_6 data[3] -> filterDate = FILTER_DATE_24 - data[4] -> {} + data[4] -> showDatePicker() } startFilter() }) { @@ -395,7 +423,7 @@ class PhotoSortingActivity : BaseActivity() { updateButtonCounts(checkSelectListContain.first) viewModel.filterResetDisplayFlow(checkSelectListContain.second) - Common.showLog( "筛选后重置 allSelectedSetList=${allSelectedSetList.size} filterSelectedSetList=${filterSelectedSetList.size} Thread=${Thread.currentThread().name}") + Common.showLog("筛选后重置 allSelectedSetList=${allSelectedSetList.size} filterSelectedSetList=${filterSelectedSetList.size} Thread=${Thread.currentThread().name}") dateAdapter?.resetAllValue(null) dateAdapter?.setData(currentList) @@ -433,5 +461,48 @@ class PhotoSortingActivity : BaseActivity() { } + fun showDatePicker() { + // 创建日期选择器构建器 + val builder = MaterialDatePicker.Builder.datePicker() + builder.setTitleText("选择日期") + // 可选:限制可选日期,比如只能选择今天之后的日期 + val constraintsBuilder = CalendarConstraints.Builder() + constraintsBuilder.setValidator(DateValidatorPointForward.now()) // 今天之后 + builder.setCalendarConstraints(constraintsBuilder.build()) + + val datePicker = builder.build() + + // 显示日期选择器 + datePicker.show(supportFragmentManager, "MATERIAL_DATE_PICKER") + + // 监听用户选择 + datePicker.addOnPositiveButtonClickListener { selection -> + // selection 是 Long 类型的时间戳(UTC 毫秒) + val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + val dateString = sdf.format(Date(selection)) + println("用户选择的日期:$dateString") + } + } + + + private fun showRecoveringDialog() { + dialogRecovering = dialogRecovering ?: RecoveringDialogFragment(filterSelectedSetList.size){ + complete() + } + dialogRecovering?.show(supportFragmentManager, "") + } + + private fun showDeletingDialog() { + dialogDeleting = dialogDeleting ?: DeletingDialogFragment(filterSelectedSetList.size){ + complete() + } + dialogDeleting?.show(supportFragmentManager, "") + } + + private fun complete() { + dialogDeleting?.dismiss() + dialogRecovering?.dismiss() + startActivity(Intent(this@PhotoSortingActivity, RecoverySuccessActivity::class.java)) + } } \ No newline at end of file diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/RecoveringDialogFragment.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/RecoveringDialogFragment.kt new file mode 100644 index 0000000..4b8385f --- /dev/null +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/RecoveringDialogFragment.kt @@ -0,0 +1,22 @@ +package com.ux.video.file.filerecovery.photo + +import com.ux.video.file.filerecovery.R +import com.ux.video.file.filerecovery.base.BaseIngDialogFragment +import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding + + +/** + * 恢复中弹窗 + */ +class RecoveringDialogFragment(total: Int, complete:()-> Unit) : BaseIngDialogFragment(total,complete) { + override fun initUi(binding: DialogRecoveringBinding) { + binding.run { + relativeLayout.setBackgroundResource(R.drawable.bg_rectangle_0048fd_top_20) + tvType.text = getString(R.string.recovering) + tvContent.text = getString(R.string.recovering_content) + tvTotal.text = total.toString() + } + } + + +} diff --git a/app/src/main/java/com/ux/video/file/filerecovery/photo/ResultPhotosFiles.kt b/app/src/main/java/com/ux/video/file/filerecovery/photo/ResultPhotosFiles.kt index 5545853..c281f76 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/photo/ResultPhotosFiles.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/photo/ResultPhotosFiles.kt @@ -8,11 +8,11 @@ import kotlinx.parcelize.Parcelize @Parcelize data class ResultPhotosFiles( val name: String, - val path: String?= null, + val path: String? = null, val size: Long, // 字节 val lastModified: Long, // 时间戳 -// var isSelected: Boolean = false // 选中状态 -): Parcelable{ + var resolution: String // 尺寸 +) : Parcelable { val targetFile: File? get() = path?.let { File(it) } } diff --git a/app/src/main/java/com/ux/video/file/filerecovery/success/RecoverySuccessActivity.kt b/app/src/main/java/com/ux/video/file/filerecovery/success/RecoverySuccessActivity.kt new file mode 100644 index 0000000..00840db --- /dev/null +++ b/app/src/main/java/com/ux/video/file/filerecovery/success/RecoverySuccessActivity.kt @@ -0,0 +1,50 @@ +package com.ux.video.file.filerecovery.success + +import android.content.Intent +import android.os.Environment +import android.view.LayoutInflater +import androidx.lifecycle.lifecycleScope +import com.ux.video.file.filerecovery.R +import com.ux.video.file.filerecovery.base.BaseActivity +import com.ux.video.file.filerecovery.databinding.ActivityRecoverOrDeletedSuccessBinding +import com.ux.video.file.filerecovery.databinding.ActivityScanningBinding +import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_AUDIO +import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_DOCUMENT +import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_PHOTO +import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_VIDEO +import com.ux.video.file.filerecovery.result.ScanResultDisplayActivity +import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo +import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video +import com.ux.video.file.filerecovery.utils.ScanManager +import com.ux.video.file.filerecovery.utils.ScanRepository +import com.ux.video.file.filerecovery.utils.ScanState +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.launch + +class RecoverySuccessActivity : BaseActivity() { + + companion object { +// val KEY_SCAN_TYPE = "scan_type" + } + + private var scanType: Int = VALUE_SCAN_TYPE_photo + override fun inflateBinding(inflater: LayoutInflater): ActivityRecoverOrDeletedSuccessBinding = + ActivityRecoverOrDeletedSuccessBinding.inflate(inflater) + + override fun initData() { + super.initData() + scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo) + binding.imageViewBack.setOnClickListener { finish() } + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/ux/video/file/filerecovery/utils/Common.kt b/app/src/main/java/com/ux/video/file/filerecovery/utils/Common.kt index f77e4a9..2fdc95b 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/utils/Common.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/utils/Common.kt @@ -172,6 +172,10 @@ object Common { return totalSelectedCount to currentSelected } + fun getFormatDate(time: Long): String{ + return dateFormat.format(Date(time)) + } + fun showLog(msg: String) { Log.d("============", msg) } diff --git a/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanManager.kt b/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanManager.kt index efe790b..9c9aeae 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanManager.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanManager.kt @@ -100,15 +100,24 @@ object ScanManager { name = file.name, path = file.absolutePath, size = file.length(), - lastModified = file.lastModified() + lastModified = file.lastModified(), + resolution = getImageSize(file).run { + "$first*$second" + } ) } ResultPhotos(dir, ArrayList(resultPhotosFilesList)) } - emit(ScanState.Complete(ArrayList(map))) } - + private fun getImageSize(file: File): Pair { + val options = BitmapFactory.Options() + options.inJustDecodeBounds = true + BitmapFactory.decodeFile(file.absolutePath, options) + val width = options.outWidth + val height = options.outHeight + return Pair(width, height) + } /** * 递归扫描隐藏目录下的有效图片(删除的图片) @@ -172,7 +181,10 @@ object ScanManager { name = file.name, path = file.absolutePath, size = file.length(), - lastModified = file.lastModified() + lastModified = file.lastModified(), + resolution = getImageSize(file).run { + "$first*$second" + } ) } ResultPhotos(dir, ArrayList(resultPhotosFilesList)) diff --git a/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanRepository.kt b/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanRepository.kt index 999c10d..0cf6e24 100644 --- a/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanRepository.kt +++ b/app/src/main/java/com/ux/video/file/filerecovery/utils/ScanRepository.kt @@ -1,5 +1,6 @@ package com.ux.video.file.filerecovery.utils +import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -32,33 +33,18 @@ class ScanRepository : ViewModel() { if (isAdd) { current.add(path) currentDisplay.add(path) -// Common.showLog( "add selected ${path}") } else { current.remove(path) currentDisplay.remove(path) -// Common.showLog( "remove selected ${path}") } Common.showLog( "toggleSelection------------ _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ") - // LiveData 使用新对象赋值,保证 observer 触发 _selectedLiveData.value = current.toSet() _selectedDisplayLiveData.value = currentDisplay.toSet() + + Log.d("CallTrace", Log.getStackTraceString(Exception("Call trace"))) + } -// fun toggleSelection(isAdd: Boolean, path: String) { -// val current = _selectedFlow.value.toMutableSet() -// val currentDisplay = _selectedDisplayFlow.value.toMutableSet() -// if (isAdd) { -// current.add(path) -// currentDisplay.add(path) -// Common.showLog( "add selected ${path}") -// } else { -// current.remove(path) -// currentDisplay.remove(path) -// Common.showLog( "remove selected ${path}") -// } -// _selectedFlow.value = current -// _selectedDisplayFlow.value = currentDisplay -// } /** * 数据筛选后重置当前显示的选中集合 diff --git a/app/src/main/res/drawable/bg_rectangle_0048fd_top_20.xml b/app/src/main/res/drawable/bg_rectangle_0048fd_top_20.xml new file mode 100644 index 0000000..b5557d9 --- /dev/null +++ b/app/src/main/res/drawable/bg_rectangle_0048fd_top_20.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_rectangle_45ffffff_top_20.xml b/app/src/main/res/drawable/bg_rectangle_45ffffff_top_20.xml new file mode 100644 index 0000000..e83a5a4 --- /dev/null +++ b/app/src/main/res/drawable/bg_rectangle_45ffffff_top_20.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_rectangle_fdad00_8.xml b/app/src/main/res/drawable/bg_rectangle_fdad00_8.xml new file mode 100644 index 0000000..e38ad28 --- /dev/null +++ b/app/src/main/res/drawable/bg_rectangle_fdad00_8.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_rectangle_fdad00_top_20.xml b/app/src/main/res/drawable/bg_rectangle_fdad00_top_20.xml new file mode 100644 index 0000000..b1120d5 --- /dev/null +++ b/app/src/main/res/drawable/bg_rectangle_fdad00_top_20.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/dialog_progress_bg.xml b/app/src/main/res/drawable/dialog_progress_bg.xml new file mode 100644 index 0000000..a5d6501 --- /dev/null +++ b/app/src/main/res/drawable/dialog_progress_bg.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/app/src/main/res/drawable/image_deleted_success.png b/app/src/main/res/drawable/image_deleted_success.png new file mode 100644 index 0000000..bd897d4 Binary files /dev/null and b/app/src/main/res/drawable/image_deleted_success.png differ diff --git a/app/src/main/res/drawable/image_recover_success.png b/app/src/main/res/drawable/image_recover_success.png new file mode 100644 index 0000000..ff06fae Binary files /dev/null and b/app/src/main/res/drawable/image_recover_success.png differ diff --git a/app/src/main/res/drawable/top_round_progress.xml b/app/src/main/res/drawable/top_round_progress.xml new file mode 100644 index 0000000..daddea2 --- /dev/null +++ b/app/src/main/res/drawable/top_round_progress.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_photo_info.xml b/app/src/main/res/layout/activity_photo_info.xml new file mode 100644 index 0000000..869664a --- /dev/null +++ b/app/src/main/res/layout/activity_photo_info.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_recover_or_deleted_success.xml b/app/src/main/res/layout/activity_recover_or_deleted_success.xml new file mode 100644 index 0000000..0ae4245 --- /dev/null +++ b/app/src/main/res/layout/activity_recover_or_deleted_success.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_scan_result_display.xml b/app/src/main/res/layout/activity_scan_result_display.xml index ff7cc3a..160f102 100644 --- a/app/src/main/res/layout/activity_scan_result_display.xml +++ b/app/src/main/res/layout/activity_scan_result_display.xml @@ -8,8 +8,6 @@ android:background="@color/white" android:orientation="vertical" tools:context=".result.ScanResultDisplayActivity"> - - + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_recovering.xml b/app/src/main/res/layout/dialog_recovering.xml new file mode 100644 index 0000000..e4cb38f --- /dev/null +++ b/app/src/main/res/layout/dialog_recovering.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5c00cd5..742d8fe 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -18,5 +18,8 @@ #C7C7CC #D5EBFF #65000000 + #0048FD + #fdad00 + #6BFFFFFF \ 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 be09a45..6a2c423 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,6 +62,17 @@ (Old to new) (New to old) OK + Name + Path + Resolution + Recovering... + It may take a few seconds to recover the file(s), please +wait.. + Deleting... + It may take a few seconds to delete the file(s), please wait.. + Recovered successfully! + Deleted successfully! + Continue All