V1.0(1)
This commit is contained in:
parent
b069402b22
commit
ca7a7f9da6
BIN
app/FileRecovery
Normal file
BIN
app/FileRecovery
Normal file
Binary file not shown.
@ -1,11 +1,16 @@
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
id ("kotlin-kapt")
|
||||
id ("kotlin-parcelize")
|
||||
id("io.objectbox")
|
||||
id("com.google.gms.google-services")
|
||||
id("com.google.firebase.crashlytics")
|
||||
}
|
||||
|
||||
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||
android {
|
||||
namespace = "com.ux.video.file.filerecovery"
|
||||
compileSdk = 36
|
||||
@ -16,13 +21,13 @@ android {
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
project.setProperty("archivesBaseName", "File Recovery Tool" + versionName + "(${versionCode})_$timestamp")
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
@ -56,9 +61,17 @@ dependencies {
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
implementation (libs.glide)
|
||||
kapt (libs.compiler)
|
||||
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
||||
implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0")
|
||||
implementation ("com.google.android.material:material:1.13.0")
|
||||
implementation(project(":pickerview"))
|
||||
implementation ("androidx.media3:media3-exoplayer:1.8.0")
|
||||
implementation ("androidx.media3:media3-ui:1.8.0")
|
||||
// implementation("androidx.core:core-splashscreen:1.0.1")
|
||||
implementation("androidx.browser:browser:1.8.0")
|
||||
|
||||
|
||||
implementation(platform("com.google.firebase:firebase-bom:34.6.0"))
|
||||
implementation("com.google.firebase:firebase-crashlytics")
|
||||
implementation("com.google.firebase:firebase-analytics")
|
||||
implementation("com.google.firebase:firebase-config")
|
||||
}
|
||||
29
app/google-services.json
Normal file
29
app/google-services.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "1034840485270",
|
||||
"project_id": "file-recovery-3d900",
|
||||
"storage_bucket": "file-recovery-3d900.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:1034840485270:android:6d9c203fa586c78cde81b7",
|
||||
"android_client_info": {
|
||||
"package_name": "com.ux.video.file.filerecovery"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyD6LDj1f2IQeA0oS6TaanB0-_B334k6PBI"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
@ -43,11 +43,6 @@
|
||||
"id": "7:8305655849151310709",
|
||||
"name": "lastModified",
|
||||
"type": 6
|
||||
},
|
||||
{
|
||||
"id": "8:5134665607056785092",
|
||||
"name": "resolution",
|
||||
"type": 9
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
@ -71,7 +66,8 @@
|
||||
3831579248666795267,
|
||||
4445203567182319472,
|
||||
6858261029979256233,
|
||||
2835789057594891780
|
||||
2835789057594891780,
|
||||
5134665607056785092
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
||||
61
app/proguard-rules.pro
vendored
61
app/proguard-rules.pro
vendored
@ -18,4 +18,63 @@
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
#-renamesourcefileattribute SourceFile
|
||||
# ========= Kotlin Parcelize =========
|
||||
-keep class kotlinx.parcelize.Parcelize
|
||||
-keep class kotlinx.android.parcel.Parcelize
|
||||
-keepclassmembers class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
# ResultDataFiles Parcelable
|
||||
-keep class com.ux.video.file.filerecovery.db.ResultDataFiles implements android.os.Parcelable {
|
||||
<fields>;
|
||||
<methods>;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.ux.video.file.filerecovery.db.ResultDataFiles {
|
||||
public static final android.os.Parcelable$Creator CREATOR;
|
||||
}
|
||||
|
||||
-keep class com.ux.video.file.filerecovery.db.ResultDataFiles { *; }
|
||||
-keep class com.ux.video.file.filerecovery.db.ResultData { *; }
|
||||
|
||||
-keep enum com.ux.video.file.filerecovery.utils.FileType { *; }
|
||||
-keep class com.ux.video.file.filerecovery.db.FileTypeConverter { *; }
|
||||
|
||||
-keep class io.objectbox.** { *; }
|
||||
-keep @io.objectbox.annotation.Entity class * { *; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ResultDataFiles Parcelable
|
||||
-keep class com.ux.video.file.filerecovery.db.ResultDataFiles implements android.os.Parcelable {
|
||||
<fields>;
|
||||
<methods>;
|
||||
}
|
||||
|
||||
-keepclassmembers class com.ux.video.file.filerecovery.db.ResultDataFiles {
|
||||
public static final android.os.Parcelable$Creator CREATOR;
|
||||
}
|
||||
|
||||
# FileType enum
|
||||
-keep enum com.ux.video.file.filerecovery.utils.FileType { *; }
|
||||
|
||||
# ObjectBox Converter
|
||||
-keep class com.ux.video.file.filerecovery.db.FileTypeConverter { *; }
|
||||
|
||||
# ObjectBox
|
||||
-keep class io.objectbox.** { *; }
|
||||
-keep @io.objectbox.annotation.Entity class * { *; }
|
||||
|
||||
# Kotlin Parcelize support
|
||||
-keep class kotlinx.parcelize.Parcelize
|
||||
-keep class kotlinx.android.parcel.Parcelize
|
||||
-keep class kotlin.Metadata { *; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -13,49 +13,76 @@
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:icon="@mipmap/recovery"
|
||||
android:label="@string/app_name"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:roundIcon="@mipmap/recovery"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.FileRecovery"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".recovery.RecoveryActivity"
|
||||
android:name=".settings.PrivacyPolicyActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".video.VideoPlayActivity"
|
||||
android:name=".settings.SetupActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".sort.PhotoInfoActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".sort.PhotoSortingActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".result.ScanResultDisplayActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".result.ScanningActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".main.ScanSelectTypeActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".documents.DocumentsScanResultActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".success.RecoverySuccessActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".main.MainActivity"
|
||||
android:exported="true">
|
||||
android:name=".welcome.SplashActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="SplashScreen">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".recovery.RecoveryActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".video.VideoPlayActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".detail.DetailsActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".sort.SortingActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".result.ScanResultDisplayActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".result.ScanningActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".main.ScanSelectTypeActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".success.RecoverySuccessActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".main.MainActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -13,6 +13,9 @@ import androidx.fragment.app.DialogFragment
|
||||
import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding
|
||||
|
||||
|
||||
/**
|
||||
* 删除/恢复中父类弹窗
|
||||
*/
|
||||
abstract class BaseIngDialogFragment() : DialogFragment() {
|
||||
var total: Int = 0
|
||||
var completeListener: ((number: Int) -> Unit)? = null
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.ux.video.file.filerecovery.db
|
||||
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import io.objectbox.converter.PropertyConverter
|
||||
|
||||
class FileTypeConverter : PropertyConverter<FileType, Int> {
|
||||
|
||||
override fun convertToDatabaseValue(entityProperty: FileType?): Int? {
|
||||
return entityProperty?.value
|
||||
}
|
||||
|
||||
override fun convertToEntityProperty(databaseValue: Int?): FileType? {
|
||||
return FileType.entries.find { it.value == databaseValue }
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,17 @@
|
||||
package com.ux.video.file.filerecovery.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.BoxStore
|
||||
import io.objectbox.config.DebugFlags
|
||||
import io.objectbox.reactive.DataSubscription
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.jvm.java
|
||||
|
||||
@ -92,6 +96,21 @@ object ObjectBoxManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fun deleteRecoveryFilesAsyncById(lifecycleCoroutineScope: LifecycleCoroutineScope,list: List<ResultDataFiles>, onComplete: () -> Unit) {
|
||||
lifecycleCoroutineScope.launch(Dispatchers.IO) {
|
||||
val objectBox = getDataBox()
|
||||
val ids = list.map { it.id }
|
||||
objectBox.removeByIds(ids)
|
||||
withContext(Dispatchers.Main) {
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// fun queryIsLike(id: Long): Boolean {
|
||||
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||
@ -113,10 +132,10 @@ object ObjectBoxManager {
|
||||
return list
|
||||
}
|
||||
|
||||
suspend fun queryRecoveryFileAsync(type: Int): List<ResultDataFiles> =
|
||||
suspend fun queryRecoveryFileAsync(type: FileType): List<ResultDataFiles> =
|
||||
withContext(Dispatchers.IO) {
|
||||
val dataBox = getDataBox()
|
||||
dataBox.query(ResultDataFiles_.fileType.equal(type))
|
||||
dataBox.query(ResultDataFiles_.fileType.equal(type.value))
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import java.io.File
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import io.objectbox.annotation.Convert
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import kotlinx.parcelize.Parcelize
|
||||
@ -13,35 +15,40 @@ import kotlinx.parcelize.Parcelize
|
||||
data class ResultDataFiles(
|
||||
@Id
|
||||
var id: Long = 0,
|
||||
// 0-3 photo\video\audio\documents
|
||||
var fileType: Int,
|
||||
|
||||
@Convert(converter = FileTypeConverter::class, dbType = Int::class)
|
||||
var fileType: FileType,
|
||||
val name: String,
|
||||
val path: String,
|
||||
val size: Long, // 字节
|
||||
val sizeString: String,
|
||||
val lastModified: Long, // 时间戳
|
||||
var resolution: String // 尺寸
|
||||
) : Parcelable {
|
||||
val targetFile: File?
|
||||
get() = path?.let { File(it) }
|
||||
// val targetFile: File
|
||||
// get() = path.let { File(it) }
|
||||
|
||||
//尺寸
|
||||
// val resolution: String
|
||||
// get() = Common.getResolution(fileType, targetFile)
|
||||
|
||||
//是否为缩略图文件(宽高任一小于 256)
|
||||
val isThumbnail: Boolean
|
||||
get() {
|
||||
val parts = resolution.lowercase().split("*").mapNotNull {
|
||||
it.trim().toIntOrNull()
|
||||
}
|
||||
if (parts.size == 2) {
|
||||
val (width, height) = parts
|
||||
return width < 256 || height < 256
|
||||
}
|
||||
return false
|
||||
}
|
||||
// val isThumbnail: Boolean
|
||||
// get() {
|
||||
// val parts = resolution.lowercase().split("*").mapNotNull {
|
||||
// it.trim().toIntOrNull()
|
||||
// }
|
||||
// if (parts.size == 2) {
|
||||
// val (width, height) = parts
|
||||
// return width < 256 || height < 256
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
|
||||
|
||||
//音视频时长
|
||||
val duration: Long
|
||||
get() {
|
||||
return Common.getMediaDuration(path.toString()) }
|
||||
// val duration: Long
|
||||
// get() {
|
||||
// return Common.getMediaDuration(path.toString())
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.ux.video.file.filerecovery.db
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 目标文件
|
||||
*/
|
||||
fun ResultDataFiles.targetFile(): File =
|
||||
File(this.path)
|
||||
|
||||
/**
|
||||
* 分辨率(图片 / 视频)
|
||||
*/
|
||||
fun ResultDataFiles.resolution(): String =
|
||||
Common.getResolution(this.fileType, targetFile())
|
||||
|
||||
/**
|
||||
* 是否缩略图(宽或高 < 256)
|
||||
*/
|
||||
fun ResultDataFiles.isThumbnail(): Boolean {
|
||||
val parts = resolution()
|
||||
.lowercase()
|
||||
.split("*")
|
||||
.mapNotNull { it.trim().toIntOrNull() }
|
||||
|
||||
if (parts.size == 2) {
|
||||
val (width, height) = parts
|
||||
return width < 256 || height < 256
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 音视频时长
|
||||
*/
|
||||
fun ResultDataFiles.duration(): Long =
|
||||
Common.getMediaDuration(this.path)
|
||||
@ -0,0 +1,300 @@
|
||||
package com.ux.video.file.filerecovery.detail
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
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.ActivityDetailsBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.duration
|
||||
import com.ux.video.file.filerecovery.db.resolution
|
||||
import com.ux.video.file.filerecovery.db.targetFile
|
||||
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
||||
import com.ux.video.file.filerecovery.success.RecoverySuccessActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanType
|
||||
import com.ux.video.file.filerecovery.video.PlayMediaManager
|
||||
import com.ux.video.file.filerecovery.video.VideoPlayActivity
|
||||
import java.io.File
|
||||
|
||||
class DetailsActivity : BaseActivity<ActivityDetailsBinding>() {
|
||||
|
||||
companion object {
|
||||
val KEY_CLICK_ITEM = "click_item"
|
||||
val KEY_SHOW_SHARE = "show_share"
|
||||
}
|
||||
|
||||
private var playMediaManager: PlayMediaManager? = null
|
||||
|
||||
private lateinit var fileType: FileType
|
||||
private var myData: ResultDataFiles? = null
|
||||
|
||||
private var showShare = false
|
||||
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityDetailsBinding =
|
||||
ActivityDetailsBinding.inflate(inflater)
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
intent.getParcelableExtra(KEY_CLICK_ITEM, ResultDataFiles::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
intent.getParcelableExtra(KEY_CLICK_ITEM)
|
||||
}
|
||||
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||
|
||||
myData?.fileType.let {
|
||||
if (it != null) {
|
||||
fileType = it
|
||||
Common.showLog("------fileType=${fileType}")
|
||||
}
|
||||
}
|
||||
showShare = intent.getBooleanExtra(KEY_SHOW_SHARE, false)
|
||||
setView()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
binding.run {
|
||||
imageViewBack.setOnClickListener { finish() }
|
||||
myData?.let { resultPhotosFiles ->
|
||||
tvName.text = resultPhotosFiles.name
|
||||
tvPath.text = resultPhotosFiles.path
|
||||
tvSize.text = resultPhotosFiles.sizeString
|
||||
tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified)
|
||||
tvResolution.text = resultPhotosFiles.resolution()
|
||||
tvDuration.text = Common.formatDuration(resultPhotosFiles.duration())
|
||||
resultPhotosFiles.targetFile().let {
|
||||
tvType.text = Common.getMimeTypeParts(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setView() {
|
||||
binding.run {
|
||||
layoutBottom.tvLeft.run {
|
||||
text = resources.getString(R.string.delete)
|
||||
setOnClickListener {
|
||||
myData?.let { myData ->
|
||||
RecoverOrDeleteManager.showConfirmDeleteDialog(
|
||||
true,
|
||||
supportFragmentManager,
|
||||
lifecycleScope,
|
||||
setOf(myData)
|
||||
) { count ->
|
||||
complete(count, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutBottom.tvRight.run {
|
||||
myData?.let { myData ->
|
||||
if (showShare) {
|
||||
text = getString(R.string.share)
|
||||
setOnClickListener {
|
||||
Common.shareSingleFile(
|
||||
this@DetailsActivity,
|
||||
myData.targetFile(),
|
||||
myData.fileType
|
||||
)
|
||||
}
|
||||
} else {
|
||||
text = getString(R.string.recover)
|
||||
setOnClickListener {
|
||||
RecoverOrDeleteManager.showRecoveringDialog(
|
||||
supportFragmentManager,
|
||||
lifecycleScope,
|
||||
setOf(myData)
|
||||
) { count ->
|
||||
complete(count, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myData?.let {
|
||||
|
||||
when (it.fileType) {
|
||||
FileType.PHOTO -> {
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutResolution.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
frameImage.setBackgroundResource(0)
|
||||
|
||||
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
layoutSize.isVisible = false
|
||||
layoutDuration.isVisible = false
|
||||
|
||||
imPlay.isVisible = false
|
||||
|
||||
myData?.targetFile()?.let { loadImage(image, it) }
|
||||
}
|
||||
|
||||
FileType.VIDEO -> {
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutResolution.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
layoutDuration.isVisible = true
|
||||
frameImage.setBackgroundResource(0)
|
||||
|
||||
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
layoutSize.isVisible = false
|
||||
|
||||
imPlay.isVisible = true
|
||||
myData?.let { data ->
|
||||
loadImage(image, data.targetFile())
|
||||
frameImage.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
this@DetailsActivity,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
putExtra(VideoPlayActivity.KEY_DATA, data)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileType.AUDIO -> {
|
||||
Common.showLog("----------音频")
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutSize.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
layoutDuration.isVisible = true
|
||||
layoutSeekbar.isVisible = true
|
||||
imPlay.isVisible = true
|
||||
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
||||
|
||||
loadCenterImage(image, R.drawable.image_info_music)
|
||||
|
||||
initPlayAudio()
|
||||
layoutResolution.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
}
|
||||
|
||||
FileType.DOCUMENT -> {
|
||||
layoutName.isVisible = true
|
||||
layoutType.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutSize.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
|
||||
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
||||
myData?.targetFile()?.let {
|
||||
loadCenterImage(image, Common.getFileIconRes(it))
|
||||
}
|
||||
imPlay.isVisible = false
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutResolution.isVisible = false
|
||||
layoutDuration.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCenterImage(image: ImageView, drawableId: Int) {
|
||||
image.setImageResource(drawableId)
|
||||
val params = image.layoutParams ?: ViewGroup.LayoutParams(
|
||||
180.dpToPx(this@DetailsActivity),
|
||||
180.dpToPx(this@DetailsActivity)
|
||||
)
|
||||
params.width = 180.dpToPx(this@DetailsActivity)
|
||||
params.height = 180.dpToPx(this@DetailsActivity)
|
||||
image.layoutParams = params
|
||||
}
|
||||
|
||||
private fun loadImage(image: ImageView, file: File) {
|
||||
Glide.with(this@DetailsActivity)
|
||||
.load(file)
|
||||
.error(R.drawable.photo_place_holder)
|
||||
.apply(
|
||||
RequestOptions().transform(
|
||||
CenterCrop(),
|
||||
RoundedCorners(8.dpToPx(this@DetailsActivity))
|
||||
)
|
||||
)
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
model: Any,
|
||||
target: Target<Drawable?>?,
|
||||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
})
|
||||
.into(image)
|
||||
}
|
||||
|
||||
|
||||
private fun initPlayAudio() {
|
||||
myData?.targetFile()?.let {
|
||||
binding.run {
|
||||
playMediaManager = PlayMediaManager(
|
||||
context = this@DetailsActivity, mediaFile = it,
|
||||
seekBar = seekBar, playBtn = imPlay, onUpdateProgress = { current, total ->
|
||||
textTimeCurrent.text = current
|
||||
textTimeTotal.text = total
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun complete(number: Int, type: Int) {
|
||||
finish()
|
||||
startActivity(Intent(this@DetailsActivity, RecoverySuccessActivity::class.java).apply {
|
||||
putExtra(RecoverySuccessActivity.Companion.KEY_SUCCESS_COUNT, number)
|
||||
putExtra(RecoverySuccessActivity.Companion.KEY_SUCCESS_TYPE, type)
|
||||
putExtra(Common.KEY_FILE_TYPE, fileType.value)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
playMediaManager?.stopPlayAudio()
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
package com.ux.video.file.filerecovery.documents
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityDocumentsScanResultBinding
|
||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
||||
|
||||
class DocumentsScanResultActivity : BaseActivity<ActivityDocumentsScanResultBinding>() {
|
||||
|
||||
|
||||
private var resultAdapter: DocumentsScanResultAdapter? = null
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityDocumentsScanResultBinding =
|
||||
ActivityDocumentsScanResultBinding.inflate(layoutInflater)
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
resultAdapter = DocumentsScanResultAdapter(this@DocumentsScanResultActivity)
|
||||
binding.recyclerView.run {
|
||||
adapter = resultAdapter
|
||||
layoutManager = LinearLayoutManager(this@DocumentsScanResultActivity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
// ScanRepository.instance.photoResults.observe(this@DocumentsScanResultActivity) {
|
||||
// resultAdapter?.setData(it)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package com.ux.video.file.filerecovery.documents
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import com.ux.video.file.filerecovery.base.BaseAdapter
|
||||
import com.ux.video.file.filerecovery.databinding.DocumentsScanResultAdapterBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
|
||||
class DocumentsScanResultAdapter(mContext: Context) :
|
||||
BaseAdapter<ResultData, DocumentsScanResultAdapterBinding>(mContext) {
|
||||
override fun getViewBinding(parent: ViewGroup): DocumentsScanResultAdapterBinding =
|
||||
DocumentsScanResultAdapterBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
|
||||
override fun bindItem(
|
||||
holder: VHolder<DocumentsScanResultAdapterBinding>,
|
||||
item: ResultData
|
||||
) {
|
||||
|
||||
holder.vb.run {
|
||||
item.run {
|
||||
tvDirName.text = dirName
|
||||
tvFileCount.text = allFiles.size.toString()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,25 +10,25 @@ import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityMainBinding
|
||||
import com.ux.video.file.filerecovery.recovery.RecoveryActivity
|
||||
import com.ux.video.file.filerecovery.sort.DatePickerDialogFragment
|
||||
import com.ux.video.file.filerecovery.settings.SetupActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||
|
||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
private var dialogCustomerDateStart:DatePickerDialogFragment? = null
|
||||
private var dialogPermission: PermissionDialogFragment? = null
|
||||
private var pendingAction: NavigateAction? = null
|
||||
private var dialogPermission: PermissionDialogFragment? = null
|
||||
|
||||
//是否正确引导用户打开所有文件管理权限
|
||||
private var isRequestPermission = false
|
||||
private var currentGoType = ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
||||
|
||||
private val requestPermissionLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||
var isAllOK = true
|
||||
@ -54,47 +54,49 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
onBackPressedDispatcher.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
ScanManager.showLog("权限", "====0000000")
|
||||
if (binding.layoutPermission.isVisible) {
|
||||
ScanManager.showLog("权限", "====111111")
|
||||
binding.layoutPermission.visibility = View.GONE
|
||||
} else {
|
||||
ScanManager.showLog("权限", "====222222222222")
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
// onBackPressedDispatcher.addCallback(
|
||||
// this,
|
||||
// object : OnBackPressedCallback(true) {
|
||||
// override fun handleOnBackPressed() {
|
||||
// ScanManager.showLog("权限", "====0000000")
|
||||
// if (binding.layoutPermission.isVisible) {
|
||||
// ScanManager.showLog("权限", "====111111")
|
||||
//// binding.layoutPermission.visibility = View.GONE
|
||||
// } else {
|
||||
// ScanManager.showLog("权限", "====222222222222")
|
||||
// finish()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
initTitleColor()
|
||||
binding.run {
|
||||
allow.setOnClickListener {
|
||||
imSetting.setOnClickListener {
|
||||
startActivity(Intent(this@MainActivity, SetupActivity::class.java))
|
||||
|
||||
}
|
||||
layoutPhoto.setOnClickListener {
|
||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
||||
pendingAction = NavigateAction.Scan(FileType.PHOTO)
|
||||
intentCheck()
|
||||
}
|
||||
layoutVideo.setOnClickListener {
|
||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_VIDEO
|
||||
pendingAction = NavigateAction.Scan(FileType.VIDEO)
|
||||
intentCheck()
|
||||
}
|
||||
layoutAudio.setOnClickListener {
|
||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_AUDIO
|
||||
pendingAction = NavigateAction.Scan(FileType.AUDIO)
|
||||
intentCheck()
|
||||
}
|
||||
layoutDocument.setOnClickListener {
|
||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
||||
pendingAction = NavigateAction.Scan(FileType.DOCUMENT)
|
||||
intentCheck()
|
||||
}
|
||||
layoutRecovery.setOnClickListener {
|
||||
startActivity(Intent(this@MainActivity,RecoveryActivity::class.java))
|
||||
pendingAction = NavigateAction.Recovered
|
||||
intentCheck()
|
||||
}
|
||||
}
|
||||
binding.tvTitle.setOnClickListener {
|
||||
@ -102,53 +104,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
showDatePicker()
|
||||
|
||||
}
|
||||
binding.btnScanAllPhoto.setOnClickListener {
|
||||
|
||||
startActivity(Intent(this@MainActivity, ScanSelectTypeActivity::class.java).apply {
|
||||
putExtra(
|
||||
ScanSelectTypeActivity.Companion.KEY_FILE_TYPE,
|
||||
ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
||||
)
|
||||
})
|
||||
}
|
||||
binding.btnScanAllVideo.setOnClickListener {
|
||||
|
||||
startActivity(Intent(this@MainActivity, ScanSelectTypeActivity::class.java).apply {
|
||||
putExtra(
|
||||
ScanSelectTypeActivity.Companion.KEY_FILE_TYPE,
|
||||
ScanSelectTypeActivity.Companion.VALUE_VIDEO
|
||||
)
|
||||
})
|
||||
}
|
||||
binding.btnScanAllAudio.setOnClickListener {
|
||||
|
||||
startActivity(Intent(this@MainActivity, ScanSelectTypeActivity::class.java).apply {
|
||||
putExtra(
|
||||
ScanSelectTypeActivity.Companion.KEY_FILE_TYPE,
|
||||
ScanSelectTypeActivity.Companion.VALUE_AUDIO
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
binding.btnScanAllFile.setOnClickListener {
|
||||
// val results = mutableListOf<ResultPhotos>()
|
||||
val root = Environment.getExternalStorageDirectory()
|
||||
|
||||
// ScanManager.scanAllDocuments(root, results)
|
||||
// ScanRepository.instance.setResults(results)
|
||||
|
||||
|
||||
|
||||
|
||||
// startActivity(Intent(this@MainActivity,DocumentsScanResultActivity::class.java))
|
||||
//
|
||||
// results.forEach { doc ->
|
||||
// ScanManager.showLog("FileScan", "目录: ${doc.dirName}, 文件数: ${doc.allFiles.size}")
|
||||
// doc.allFiles.forEach { file ->
|
||||
// ScanManager.showLog("FileScan", " -> 文件: ${file.targetFile.isHidden} ")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private fun initTitleColor() {
|
||||
@ -158,7 +113,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
val width = paint.measureText(text.toString())
|
||||
val shader = LinearGradient(
|
||||
0f, 0f, width, textSize,
|
||||
intArrayOf(getColor(R.color.color_title_start_color),getColor(R.color.color_title_end_color)),
|
||||
intArrayOf(
|
||||
getColor(R.color.color_title_start_color),
|
||||
getColor(R.color.color_title_end_color)
|
||||
),
|
||||
null,
|
||||
Shader.TileMode.CLAMP
|
||||
)
|
||||
@ -177,7 +135,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
isRequestPermission = false
|
||||
ScanManager.showLog("--", "-------onResume")
|
||||
startScan()
|
||||
binding.layoutPermission.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +168,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
private fun requestPermission() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
dialogPermission = dialogPermission?: PermissionDialogFragment{
|
||||
dialogPermission = dialogPermission ?: PermissionDialogFragment {
|
||||
try {
|
||||
val intent =
|
||||
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
|
||||
@ -224,7 +181,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
isRequestPermission = true
|
||||
}
|
||||
dialogPermission?.show(supportFragmentManager,"")
|
||||
dialogPermission?.show(supportFragmentManager, "")
|
||||
} else {
|
||||
requestPermissionLauncher.launch(
|
||||
arrayOf(
|
||||
@ -236,14 +193,31 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
|
||||
private fun startScan() {
|
||||
startActivity(Intent(this@MainActivity, ScanSelectTypeActivity::class.java).apply {
|
||||
putExtra(ScanSelectTypeActivity.Companion.KEY_FILE_TYPE, currentGoType)
|
||||
})
|
||||
|
||||
when (val action = pendingAction) {
|
||||
is NavigateAction.Scan -> startActivity(
|
||||
Intent(
|
||||
this@MainActivity,
|
||||
ScanSelectTypeActivity::class.java
|
||||
).apply {
|
||||
putExtra(Common.KEY_FILE_TYPE, action.fileType.value)
|
||||
})
|
||||
|
||||
NavigateAction.Recovered -> startActivity(
|
||||
Intent(
|
||||
this@MainActivity,
|
||||
RecoveryActivity::class.java
|
||||
)
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
pendingAction = null
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
binding.layoutPermission.isVisible = false
|
||||
// binding.layoutPermission.isVisible = false
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
package com.ux.video.file.filerecovery.main
|
||||
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
sealed class NavigateAction {
|
||||
data class Scan(val fileType: FileType) : NavigateAction()
|
||||
object Recovered : NavigateAction()
|
||||
}
|
||||
@ -6,15 +6,9 @@ import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityScanSelectTypeBinding
|
||||
import com.ux.video.file.filerecovery.result.ScanningActivity
|
||||
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.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanType
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
||||
@ -23,14 +17,6 @@ import kotlin.properties.Delegates
|
||||
*/
|
||||
class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
||||
|
||||
companion object {
|
||||
val KEY_FILE_TYPE = "file_type"
|
||||
val VALUE_PHOTO = 0
|
||||
val VALUE_VIDEO = 1
|
||||
val VALUE_AUDIO = 2
|
||||
val VALUE_DOCUMENT = 3
|
||||
}
|
||||
|
||||
private var allType by Delegates.notNull<Int>()
|
||||
private var deletedType by Delegates.notNull<Int>()
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityScanSelectTypeBinding =
|
||||
@ -39,8 +25,10 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
val type = intent.getIntExtra(KEY_FILE_TYPE, VALUE_PHOTO)
|
||||
setSelectType(type)
|
||||
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||
val fileType = FileType.from(intExtra)
|
||||
fileType?.let { setSelectType(it) }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -50,40 +38,40 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
||||
binding.scanAllFile.setOnClickListener {
|
||||
|
||||
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
|
||||
putExtra(KEY_SCAN_TYPE, allType)
|
||||
putExtra(Common.KEY_SCAN_TYPE, allType)
|
||||
})
|
||||
|
||||
}
|
||||
binding.scanDeletedFile.setOnClickListener {
|
||||
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
|
||||
putExtra(KEY_SCAN_TYPE, deletedType)
|
||||
putExtra(Common.KEY_SCAN_TYPE, deletedType)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSelectType(fileType: Int) {
|
||||
private fun setSelectType(fileType: FileType) {
|
||||
when (fileType) {
|
||||
VALUE_PHOTO -> {
|
||||
allType = VALUE_SCAN_TYPE_photo
|
||||
deletedType = VALUE_SCAN_TYPE_deleted_photo
|
||||
FileType.PHOTO -> {
|
||||
allType = ScanType.ALL_PHOTO.value
|
||||
deletedType = ScanType.DELETED_PHOTO.value
|
||||
binding.title.text = getString(R.string.photo_title)
|
||||
}
|
||||
|
||||
VALUE_VIDEO -> {
|
||||
allType = VALUE_SCAN_TYPE_video
|
||||
deletedType = VALUE_SCAN_TYPE_deleted_video
|
||||
FileType.VIDEO -> {
|
||||
allType = ScanType.ALL_VIDEO.value
|
||||
deletedType = ScanType.DELETED_VIDEO.value
|
||||
binding.title.text = getString(R.string.video_title)
|
||||
}
|
||||
|
||||
VALUE_AUDIO -> {
|
||||
allType = VALUE_SCAN_TYPE_audio
|
||||
deletedType = VALUE_SCAN_TYPE_deleted_audio
|
||||
FileType.AUDIO -> {
|
||||
allType = ScanType.ALL_AUDIO.value
|
||||
deletedType = ScanType.DELETED_AUDIO.value
|
||||
binding.title.text = getString(R.string.audio_title)
|
||||
}
|
||||
|
||||
VALUE_DOCUMENT -> {
|
||||
allType = VALUE_SCAN_TYPE_documents
|
||||
deletedType = VALUE_SCAN_TYPE_deleted_documents
|
||||
FileType.DOCUMENT -> {
|
||||
allType = ScanType.ALL_DOCUMENT.value
|
||||
deletedType = ScanType.DELETED_DOCUMENT.value
|
||||
binding.title.text = getString(R.string.document_title)
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,26 +11,32 @@ import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityRecoveryBinding
|
||||
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
||||
import com.ux.video.file.filerecovery.recovery.ui.MyViewPage2Adapter
|
||||
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoFragment
|
||||
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveredFragment
|
||||
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
||||
val sharedViewModel: RecoveryPhotoViewModel by viewModels()
|
||||
private lateinit var fileType: FileType
|
||||
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding =
|
||||
ActivityRecoveryBinding.inflate(inflater)
|
||||
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||
fileType = FileType.from(intExtra)!!
|
||||
binding.run {
|
||||
val fragments = listOf(
|
||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_PHOTO),
|
||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_VIDEO),
|
||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_AUDIO),
|
||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_DOCUMENTS)
|
||||
RecoveredFragment.newInstance(FileType.PHOTO.value),
|
||||
RecoveredFragment.newInstance(FileType.VIDEO.value),
|
||||
RecoveredFragment.newInstance(FileType.AUDIO.value),
|
||||
RecoveredFragment.newInstance(FileType.DOCUMENT.value)
|
||||
)
|
||||
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity, fragments)
|
||||
TabLayoutMediator(tabLayout, viewPage2) { tab, position ->
|
||||
@ -74,6 +80,17 @@ class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
||||
|
||||
})
|
||||
|
||||
ScanManager.showLog("-----tt-------", "-------fileType=${fileType}")
|
||||
fileType.run {
|
||||
when (this) {
|
||||
FileType.PHOTO -> viewPage2.currentItem = 0
|
||||
FileType.VIDEO -> viewPage2.currentItem = 1
|
||||
FileType.AUDIO -> viewPage2.currentItem = 2
|
||||
FileType.DOCUMENT -> viewPage2.currentItem = 3
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,27 +99,48 @@ class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
||||
binding.imageBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
sharedViewModel.photoFiles.observe(this) {
|
||||
setTabCount( FileType.PHOTO, it.size)
|
||||
}
|
||||
sharedViewModel.videoFiles.observe(this) {
|
||||
setTabCount( FileType.VIDEO, it.size)
|
||||
}
|
||||
sharedViewModel.audioFiles.observe(this) {
|
||||
setTabCount( FileType.AUDIO, it.size)
|
||||
}
|
||||
sharedViewModel.documentsFiles.observe(this) {
|
||||
setTabCount(FileType.DOCUMENT, it.size)
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_PHOTO)
|
||||
sharedViewModel.setPhotosRecoveredFiles(recoveryFilePhoto)
|
||||
val recoveryFileVideo = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_VIDEO)
|
||||
sharedViewModel.setVideosRecoveredFiles(recoveryFileVideo)
|
||||
val recoveryFileAudio = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_AUDIO)
|
||||
sharedViewModel.setAudiosRecoveredFiles(recoveryFileAudio)
|
||||
val recoveryFileDocuments =
|
||||
ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_DOCUMENTS)
|
||||
sharedViewModel.setDocumentsRecoveredFiles(recoveryFileDocuments)
|
||||
binding.tabLayout.run {
|
||||
getTabAt(0)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
getString(R.string.text_counts, recoveryFilePhoto.size)
|
||||
getTabAt(1)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
getString(R.string.text_counts, recoveryFileVideo.size)
|
||||
getTabAt(2)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
getString(R.string.text_counts, recoveryFileAudio.size)
|
||||
getTabAt(3)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
getString(R.string.text_counts, recoveryFileDocuments.size)
|
||||
FileType.entries.forEach{ fileType->
|
||||
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(fileType)
|
||||
sharedViewModel.setRecoveredFiles(fileType, recoveryFilePhoto)
|
||||
setTabCount(fileType, recoveryFilePhoto.size)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setTabCount(fileType: FileType, number: Int) {
|
||||
binding.tabLayout.run {
|
||||
getTabAt(fileType.tabIndex)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
getString(R.string.text_counts, number)
|
||||
// when (fileType) {
|
||||
// FileType.PHOTO -> getTabAt(0)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
// getString(R.string.text_counts, number)
|
||||
//
|
||||
// FileType.VIDEO -> getTabAt(1)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
// getString(R.string.text_counts, number)
|
||||
//
|
||||
// FileType.AUDIO -> getTabAt(2)?.customView?.findViewById<CustomTextView>(R.id.tab_item_count)?.text =
|
||||
// getString(R.string.text_counts, number)
|
||||
//
|
||||
// FileType.DOCUMENT -> getTabAt(3)?.customView?.findViewById<CustomTextView>(
|
||||
// R.id.tab_item_count
|
||||
// )?.text =
|
||||
// getString(R.string.text_counts, number)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
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.DialogDeleteSuccessBinding
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
|
||||
class DeleteSuccessDialog(): DialogFragment() {
|
||||
private lateinit var binding: DialogDeleteSuccessBinding
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
isCancelable = false
|
||||
dialog?.window?.apply {
|
||||
setLayout(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||
val params = attributes
|
||||
params.gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
||||
params.y = 100.dpToPx(context)
|
||||
attributes = params
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
|
||||
binding = DialogDeleteSuccessBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,297 @@
|
||||
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseFragment
|
||||
import com.ux.video.file.filerecovery.databinding.FragmentRecoveryPhotoBinding
|
||||
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
||||
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.targetFile
|
||||
import com.ux.video.file.filerecovery.detail.DetailsActivity
|
||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity
|
||||
import com.ux.video.file.filerecovery.sort.SortDisplayChildAdapter
|
||||
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
|
||||
class RecoveredFragment : BaseFragment<FragmentRecoveryPhotoBinding>() {
|
||||
|
||||
companion object {
|
||||
private const val ARG_FILE_TYPE = "arg_file_type"
|
||||
|
||||
fun newInstance(fileType: Int): RecoveredFragment {
|
||||
val fragment = RecoveredFragment()
|
||||
val args = Bundle().apply {
|
||||
putInt(ARG_FILE_TYPE, fileType)
|
||||
}
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var fileType: FileType? = null
|
||||
|
||||
private var mAdapter: SortDisplayChildAdapter? = null
|
||||
private var selectedList: Set<ResultDataFiles>? = null
|
||||
|
||||
|
||||
private val sharedViewModel: RecoveryPhotoViewModel by activityViewModels()
|
||||
private lateinit var recoveredList: List<ResultDataFiles>
|
||||
|
||||
|
||||
override fun initBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
): FragmentRecoveryPhotoBinding =
|
||||
FragmentRecoveryPhotoBinding.inflate(inflater, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val i = arguments?.getInt(ARG_FILE_TYPE) ?: FileType.PHOTO.value
|
||||
fileType = FileType.from(i)
|
||||
binding.run {
|
||||
fileType?.let {
|
||||
when (it) {
|
||||
FileType.PHOTO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_photos)
|
||||
sharedViewModel.photoFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, FileType.PHOTO)
|
||||
}
|
||||
sharedViewModel.selectedPhoto.observe(viewLifecycleOwner) { displaySet ->
|
||||
selectedList = displaySet
|
||||
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
|
||||
selectedList?.let {
|
||||
updateSelectStatus(it.size)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FileType.VIDEO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_videos)
|
||||
sharedViewModel.videoFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, FileType.VIDEO )
|
||||
}
|
||||
sharedViewModel.selectedVideo.observe(viewLifecycleOwner) { displaySet ->
|
||||
selectedList = displaySet
|
||||
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
|
||||
selectedList?.let {
|
||||
updateSelectStatus(it.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileType.AUDIO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_audios)
|
||||
sharedViewModel.audioFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, FileType.AUDIO )
|
||||
}
|
||||
sharedViewModel.selectedAudio.observe(viewLifecycleOwner) { displaySet ->
|
||||
selectedList = displaySet
|
||||
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
|
||||
selectedList?.let {
|
||||
updateSelectStatus(it.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileType.DOCUMENT -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_documents)
|
||||
sharedViewModel.documentsFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, FileType.DOCUMENT)
|
||||
}
|
||||
sharedViewModel.selectedDocuments.observe(viewLifecycleOwner) { displaySet ->
|
||||
selectedList = displaySet
|
||||
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
|
||||
selectedList?.let {
|
||||
updateSelectStatus(it.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSelectStatus(0)
|
||||
initClick()
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun initViewVisible(list: List<ResultDataFiles>) {
|
||||
recoveredList = list
|
||||
binding.run {
|
||||
recyclerView.isVisible = list.isNotEmpty()
|
||||
layoutEmpty.relativeEmptyMain.isVisible = !list.isNotEmpty()
|
||||
layoutBottom.run {
|
||||
bottomMainLayout.isVisible = list.isNotEmpty()
|
||||
// tvRight.text = getString(R.string.share)
|
||||
}
|
||||
tvAllSelect.isVisible = list.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSelectStatus(selectedCounts: Int) {
|
||||
binding.run {
|
||||
selectedCounts.let {
|
||||
tvAllSelect.isSelected = it == mAdapter?.itemCount
|
||||
if (it <= 0) {
|
||||
layoutBottom.tvLeft.isEnabled = false
|
||||
layoutBottom.tvRight.isEnabled = false
|
||||
} else {
|
||||
layoutBottom.tvLeft.isEnabled = true
|
||||
layoutBottom.tvRight.isEnabled = true
|
||||
}
|
||||
layoutBottom.tvLeft.text = getString(R.string.delete_placeholder, it)
|
||||
layoutBottom.tvRight.text = getString(R.string.share_placeholder, it)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setRecoveredData(list: List<ResultDataFiles>, fileType: FileType) {
|
||||
|
||||
mAdapter = SortDisplayChildAdapter(
|
||||
mContext = requireContext(),
|
||||
fileType = fileType,
|
||||
mColumns = 2,
|
||||
viewModel = sharedViewModel,
|
||||
onSelectedUpdate = { resultPhotosFiles, isAdd, allSelected ->
|
||||
fileType?.let { sharedViewModel.toggleSelection(it, isAdd, resultPhotosFiles) }
|
||||
|
||||
|
||||
},
|
||||
hideThumbnailsUpdate = { hide ->
|
||||
|
||||
}) { item ->
|
||||
|
||||
startActivity(
|
||||
Intent(
|
||||
requireContext(),
|
||||
DetailsActivity::class.java
|
||||
).apply {
|
||||
putExtra(KEY_SCAN_TYPE, fileType.value)
|
||||
putExtra(DetailsActivity.KEY_CLICK_ITEM, item)
|
||||
putExtra(DetailsActivity.KEY_SHOW_SHARE, true)
|
||||
})
|
||||
|
||||
}.apply {
|
||||
setData(list)
|
||||
}
|
||||
|
||||
binding.recyclerView.run {
|
||||
adapter = mAdapter
|
||||
when (fileType) {
|
||||
FileType.PHOTO, FileType.VIDEO -> {
|
||||
layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
val bPx = 6.dpToPx(context)
|
||||
val aPx = 16.dpToPx(context)
|
||||
val bottom = 75.dpToPx(context)
|
||||
setPadding(aPx, 0, bPx, bottom)
|
||||
}
|
||||
|
||||
|
||||
FileType.AUDIO , FileType.DOCUMENT -> {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
val bPx = 6.dpToPx(context)
|
||||
val aPx = 16.dpToPx(context)
|
||||
val bottom = 75.dpToPx(context)
|
||||
setPadding(aPx, 0, bPx, bottom)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun initClick() {
|
||||
binding.run {
|
||||
|
||||
fileType?.let { fileType ->
|
||||
layoutEmpty.tvScan.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
requireActivity(),
|
||||
ScanSelectTypeActivity::class.java
|
||||
).apply {
|
||||
putExtra(Common.KEY_FILE_TYPE, fileType.value)
|
||||
})
|
||||
requireActivity().finish()
|
||||
}
|
||||
tvAllSelect.setOnClickListener {
|
||||
it.isSelected = !it.isSelected
|
||||
mAdapter?.setAllSelected(it.isSelected)
|
||||
|
||||
}
|
||||
layoutBottom.tvLeft.setOnClickListener {
|
||||
selectedList?.let {
|
||||
RecoverOrDeleteManager.showConfirmDeleteDialog(
|
||||
fragmentManager = requireActivity().supportFragmentManager,
|
||||
scope = lifecycleScope,
|
||||
selectedSetList = it
|
||||
) { count ->
|
||||
val removeSelectedFromSizeList =
|
||||
sharedViewModel.removeSelectedFromSizeList(recoveredList, it)
|
||||
ObjectBoxManager.deleteRecoveryFilesAsyncById(
|
||||
lifecycleScope,
|
||||
it.toList()
|
||||
) {}
|
||||
sharedViewModel.setRecoveredFiles(fileType, removeSelectedFromSizeList)
|
||||
sharedViewModel.clearSelected(fileType)
|
||||
showCustomToast(requireContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layoutBottom.tvRight.setOnClickListener {
|
||||
selectedList?.let { list->
|
||||
if (list.size == 1) {
|
||||
list.first().targetFile().let { file ->
|
||||
Common.shareSingleFile(requireActivity(), file, fileType)
|
||||
}
|
||||
} else if (list.isNotEmpty()) {
|
||||
val toList = list.map { it.targetFile() }.toList()
|
||||
Common.shareMultipleFiles(requireActivity(), toList, fileType)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun showCustomToast(context: Context) {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
Toast(context).apply {
|
||||
duration = Toast.LENGTH_SHORT
|
||||
this.view = inflater.inflate(R.layout.dialog_delete_success, null)
|
||||
setGravity(Gravity.CENTER_HORIZONTAL or Gravity.TOP, 0, 150.dpToPx(context))
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseFragment
|
||||
import com.ux.video.file.filerecovery.databinding.FragmentRecoveryPhotoBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.sort.PhotoDisplayDateAdapter
|
||||
import com.ux.video.file.filerecovery.sort.PhotoDisplayDateChildAdapter
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
|
||||
|
||||
class RecoveryPhotoFragment : BaseFragment<FragmentRecoveryPhotoBinding>() {
|
||||
|
||||
companion object {
|
||||
private const val ARG_FILE_TYPE = "arg_file_type"
|
||||
|
||||
fun newInstance(fileType: Int): RecoveryPhotoFragment {
|
||||
val fragment = RecoveryPhotoFragment()
|
||||
val args = Bundle().apply {
|
||||
putInt(ARG_FILE_TYPE, fileType)
|
||||
}
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
// 0-3 photo\video\audio\documents
|
||||
private var fileType: Int = Common.FILE_TYPE_PHOTO
|
||||
|
||||
private lateinit var mAdapter: PhotoDisplayDateChildAdapter
|
||||
private var selectedList: List<ResultDataFiles>? = null
|
||||
|
||||
|
||||
private val sharedViewModel: RecoveryPhotoViewModel by activityViewModels()
|
||||
|
||||
override fun initBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
): FragmentRecoveryPhotoBinding =
|
||||
FragmentRecoveryPhotoBinding.inflate(inflater, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
fileType = arguments?.getInt(ARG_FILE_TYPE) ?: Common.FILE_TYPE_PHOTO
|
||||
|
||||
|
||||
binding.run {
|
||||
when (fileType) {
|
||||
Common.FILE_TYPE_PHOTO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_photos)
|
||||
sharedViewModel.photoFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, Common.VALUE_SCAN_TYPE_photo)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Common.FILE_TYPE_VIDEO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_videos)
|
||||
sharedViewModel.videoFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, Common.VALUE_SCAN_TYPE_video)
|
||||
}
|
||||
}
|
||||
|
||||
Common.FILE_TYPE_AUDIO -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_audios)
|
||||
sharedViewModel.audioFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, Common.VALUE_SCAN_TYPE_audio)
|
||||
}
|
||||
}
|
||||
|
||||
Common.FILE_TYPE_DOCUMENTS -> {
|
||||
layoutEmpty.tvScan.text = getString(R.string.scan_documents)
|
||||
sharedViewModel.documentsFiles.observe(viewLifecycleOwner) {
|
||||
initViewVisible(it)
|
||||
setRecoveredData(it, Common.VALUE_SCAN_TYPE_documents)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
sharedViewModel.selectedLiveData.observe(viewLifecycleOwner) { displaySet ->
|
||||
selectedList = displaySet.toList()
|
||||
Common.showLog("当前显示筛选数据 选中状态更新: ${displaySet.size}")
|
||||
selectedList?.let {
|
||||
updateSelectStatus(it.size)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
initClick()
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun initViewVisible(list: List<ResultDataFiles>) {
|
||||
binding.run {
|
||||
recyclerView.isVisible = list.isNotEmpty()
|
||||
layoutEmpty.relativeEmptyMain.isVisible = !list.isNotEmpty()
|
||||
layoutBottom.run {
|
||||
bottomMainLayout.isVisible = list.isNotEmpty()
|
||||
// tvRight.text = getString(R.string.share)
|
||||
}
|
||||
tvAllSelect.isVisible = list.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSelectStatus(selectedCounts: Int) {
|
||||
binding.run {
|
||||
selectedCounts.let {
|
||||
tvAllSelect.isSelected = it == mAdapter.itemCount
|
||||
if (it <= 0) {
|
||||
layoutBottom.tvLeft.isEnabled = false
|
||||
layoutBottom.tvRight.isEnabled = false
|
||||
} else {
|
||||
layoutBottom.tvLeft.isEnabled = true
|
||||
layoutBottom.tvRight.isEnabled = true
|
||||
}
|
||||
layoutBottom.tvLeft.text = getString(R.string.delete_placeholder, it)
|
||||
layoutBottom.tvRight.text = getString(R.string.share_placeholder, it)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setRecoveredData(list: List<ResultDataFiles>, scanTye: Int) {
|
||||
|
||||
mAdapter = PhotoDisplayDateChildAdapter(
|
||||
mContext = requireContext(),
|
||||
scanType = scanTye,
|
||||
mColumns = 2,
|
||||
viewModel = sharedViewModel,
|
||||
onSelectedUpdate = { resultPhotosFiles, isAdd, allSelected ->
|
||||
sharedViewModel.toggleSelection(isAdd, resultPhotosFiles)
|
||||
|
||||
},
|
||||
hideThumbnailsUpdate = { hide ->
|
||||
|
||||
}) { item ->
|
||||
|
||||
}.apply {
|
||||
setData(list)
|
||||
}
|
||||
updateSelectStatus(0)
|
||||
binding.recyclerView.run {
|
||||
adapter = mAdapter
|
||||
when (scanTye) {
|
||||
Common.VALUE_SCAN_TYPE_photo, Common.VALUE_SCAN_TYPE_video -> {
|
||||
layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
val bPx = 6.dpToPx(context)
|
||||
val aPx = 16.dpToPx(context)
|
||||
val bottom = 75.dpToPx(context)
|
||||
setPadding(aPx, 0, bPx, bottom)
|
||||
}
|
||||
|
||||
|
||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_documents -> {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
val bPx = 6.dpToPx(context)
|
||||
val aPx = 16.dpToPx(context)
|
||||
val bottom = 75.dpToPx(context)
|
||||
setPadding(aPx, 0, bPx, bottom)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun initClick() {
|
||||
binding.tvAllSelect.setOnClickListener {
|
||||
it.isSelected = !it.isSelected
|
||||
mAdapter.setAllSelected(it.isSelected)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,50 +5,102 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
/**
|
||||
*
|
||||
* RecoveryActivity RecoveredFragment 共用
|
||||
*/
|
||||
class RecoveryPhotoViewModel : ViewModel() {
|
||||
private val _photoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
||||
|
||||
//用于及时更新tab 显示恢复文件的数量
|
||||
private val _photoFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||
val photoFiles: LiveData<List<ResultDataFiles>> = _photoFiles
|
||||
|
||||
private val _videoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
||||
val videoFiles: LiveData< List<ResultDataFiles>> = _videoFiles
|
||||
private val _videoFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||
val videoFiles: LiveData<List<ResultDataFiles>> = _videoFiles
|
||||
|
||||
private val _audioFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
||||
val audioFiles: LiveData< List<ResultDataFiles>> = _audioFiles
|
||||
private val _audioFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||
val audioFiles: LiveData<List<ResultDataFiles>> = _audioFiles
|
||||
|
||||
private val _documentsFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
||||
val documentsFiles: LiveData< List<ResultDataFiles>> = _documentsFiles
|
||||
private val _documentsFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||
val documentsFiles: LiveData<List<ResultDataFiles>> = _documentsFiles
|
||||
|
||||
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
|
||||
|
||||
fun setPhotosRecoveredFiles(photos:List<ResultDataFiles>){
|
||||
_photoFiles.value = photos
|
||||
}
|
||||
fun setVideosRecoveredFiles(videos:List<ResultDataFiles>){
|
||||
_videoFiles.value = videos
|
||||
}
|
||||
fun setAudiosRecoveredFiles(audios:List<ResultDataFiles>){
|
||||
_audioFiles.value = audios
|
||||
}
|
||||
fun setDocumentsRecoveredFiles(documents:List<ResultDataFiles>){
|
||||
_documentsFiles.value = documents
|
||||
}
|
||||
private val _selectedPhotoLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedPhoto: LiveData<Set<ResultDataFiles>> = _selectedPhotoLiveData
|
||||
|
||||
fun toggleSelection(isAdd: Boolean, resultDataFiles: ResultDataFiles) {
|
||||
val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
|
||||
resultDataFiles.let {
|
||||
if (isAdd) {
|
||||
current.add(it)
|
||||
} else {
|
||||
current.remove(it)
|
||||
}
|
||||
private val _selectedVideoLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedVideo: LiveData<Set<ResultDataFiles>> = _selectedVideoLiveData
|
||||
|
||||
private val _selectedAudioLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedAudio: LiveData<Set<ResultDataFiles>> = _selectedAudioLiveData
|
||||
|
||||
private val _selectedDocumentsLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedDocuments: LiveData<Set<ResultDataFiles>> = _selectedDocumentsLiveData
|
||||
|
||||
|
||||
fun setRecoveredFiles(fileType: FileType, data: List<ResultDataFiles>) {
|
||||
when (fileType) {
|
||||
FileType.PHOTO -> _photoFiles.value = data
|
||||
FileType.VIDEO -> _videoFiles.value = data
|
||||
FileType.AUDIO -> _audioFiles.value = data
|
||||
FileType.DOCUMENT -> _documentsFiles.value = data
|
||||
}
|
||||
_selectedLiveData.value = current.toSet()
|
||||
|
||||
}
|
||||
|
||||
fun checkIsSelect(resultDataFiles: ResultDataFiles): Boolean {
|
||||
val current = _selectedLiveData.value
|
||||
return current?.contains(resultDataFiles) == true
|
||||
|
||||
fun toggleSelection(fileType: FileType, isAdd: Boolean, resultDataFiles: ResultDataFiles) {
|
||||
getSelectedList(fileType).let { selectList ->
|
||||
val current = selectList.value?.toMutableSet() ?: mutableSetOf()
|
||||
resultDataFiles.let {
|
||||
if (isAdd) {
|
||||
current.add(it)
|
||||
} else {
|
||||
current.remove(it)
|
||||
}
|
||||
}
|
||||
selectList.value = current.toSet()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun clearSelected(fileType: FileType) {
|
||||
getSelectedList(fileType).let {
|
||||
it.value = it.value?.toMutableSet()?.apply {
|
||||
clear()
|
||||
} ?: emptySet()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun removeSelectedFromSizeList(
|
||||
list: List<ResultDataFiles>,
|
||||
selectedLiveData: Set<ResultDataFiles>
|
||||
): List<ResultDataFiles> {
|
||||
return list.filterNot { it in selectedLiveData }
|
||||
}
|
||||
|
||||
|
||||
fun checkIsSelect(fileType: FileType, resultDataFiles: ResultDataFiles): Boolean {
|
||||
return when (fileType) {
|
||||
FileType.PHOTO -> _selectedPhotoLiveData
|
||||
FileType.VIDEO-> _selectedVideoLiveData
|
||||
FileType.AUDIO -> _selectedAudioLiveData
|
||||
FileType.DOCUMENT -> _selectedDocumentsLiveData
|
||||
}.let {
|
||||
val current = it.value
|
||||
current?.contains(resultDataFiles) == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedList(fileType: FileType): MutableLiveData<Set<ResultDataFiles>> {
|
||||
return when (fileType) {
|
||||
FileType.PHOTO -> _selectedPhotoLiveData
|
||||
FileType.VIDEO -> _selectedVideoLiveData
|
||||
FileType.AUDIO -> _selectedAudioLiveData
|
||||
FileType.DOCUMENT -> _selectedDocumentsLiveData
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,48 +3,37 @@ package com.ux.video.file.filerecovery.result
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.viewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityScanResultDisplayBinding
|
||||
import com.ux.video.file.filerecovery.sort.PhotoSortingActivity
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
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.ExtendFunctions.getParcelableArrayListExtraCompat
|
||||
import com.ux.video.file.filerecovery.sort.SortingActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanType
|
||||
|
||||
/**
|
||||
* 扫描结果汇总展示
|
||||
*/
|
||||
class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>() {
|
||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||
private lateinit var scanType: ScanType
|
||||
private var exitDialog: ExitDialogFragment? = null
|
||||
|
||||
private var list: ArrayList<ResultData>? = null
|
||||
private lateinit var list: List<ResultData>
|
||||
private val viewModel: ScanningResultDisplayViewModel by viewModels()
|
||||
|
||||
companion object {
|
||||
val KEY_SCAN_RESULT = "scan_result"
|
||||
|
||||
}
|
||||
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityScanResultDisplayBinding =
|
||||
ActivityScanResultDisplayBinding.inflate(inflater)
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
list = intent.getParcelableArrayListExtraCompat(KEY_SCAN_RESULT)
|
||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||
setSelectTypeTitle(scanType)
|
||||
|
||||
|
||||
val intExtra = intent.getIntExtra(Common.KEY_SCAN_TYPE, ScanType.ALL_PHOTO.value)
|
||||
scanType = ScanType.from(intExtra)!!
|
||||
setSelectTypeTitle(scanType.mediaType)
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
@ -59,12 +48,12 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
||||
})
|
||||
|
||||
binding.run {
|
||||
val myAdapter = when (scanType) {
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
val myAdapter = when (scanType.mediaType) {
|
||||
FileType.AUDIO, FileType.DOCUMENT -> {
|
||||
bottomLayout.setBackgroundResource(R.drawable.bg_rectangle_white_top_20)
|
||||
ScanResultDocumentsAdapter(
|
||||
ScanResultDocumentsAudioAdapter(
|
||||
this@ScanResultDisplayActivity,
|
||||
scanType
|
||||
scanType.mediaType
|
||||
) { folderLists ->
|
||||
goSort(folderLists)
|
||||
}
|
||||
@ -72,60 +61,56 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
||||
|
||||
else -> {
|
||||
bottomLayout.setBackgroundResource(0)
|
||||
ScanResultPhotoAdapter(
|
||||
ScanResultPhotoVideoAdapter(
|
||||
this@ScanResultDisplayActivity,
|
||||
scanType
|
||||
scanType.mediaType
|
||||
) { folderLists ->
|
||||
goSort(folderLists)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}.apply {
|
||||
list?.let {
|
||||
textDirCount.text = it.size.toString()
|
||||
val sumOf = it.sumOf { it.allFiles.size }
|
||||
}
|
||||
viewModel.scanData.observe(this@ScanResultDisplayActivity){ data->
|
||||
list = data
|
||||
list.let { data ->
|
||||
textDirCount.text = data.size.toString()
|
||||
val sumOf = data.sumOf { it.allFiles.size }
|
||||
textAllCounts.text = sumOf.toString()
|
||||
setData(it)
|
||||
myAdapter.setData(data)
|
||||
}
|
||||
}
|
||||
recyclerResult.run {
|
||||
adapter = myAdapter
|
||||
layoutManager = LinearLayoutManager(this@ScanResultDisplayActivity)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun dealExit() {
|
||||
exitDialog = exitDialog ?: ExitDialogFragment() {
|
||||
exitDialog = exitDialog ?: ExitDialogFragment {
|
||||
finish()
|
||||
}
|
||||
exitDialog?.show(supportFragmentManager, "")
|
||||
}
|
||||
|
||||
private fun setSelectTypeTitle(fileType: Int) {
|
||||
private fun setSelectTypeTitle(fileType: FileType) {
|
||||
binding.run {
|
||||
when (fileType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
FileType.PHOTO -> {
|
||||
title.text = getString(R.string.photo_title)
|
||||
textFileType.text = getString(R.string.text_photos)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
|
||||
FileType.VIDEO-> {
|
||||
title.text = getString(R.string.video_title)
|
||||
textFileType.text = getString(R.string.text_videos)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
FileType.AUDIO -> {
|
||||
title.text = getString(R.string.audio_title)
|
||||
textFileType.text = getString(R.string.text_audios)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
FileType.DOCUMENT -> {
|
||||
title.text = getString(R.string.document_title)
|
||||
textFileType.text = getString(R.string.text_documents)
|
||||
}
|
||||
@ -137,16 +122,13 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
||||
|
||||
|
||||
private fun goSort(list: ArrayList<ResultDataFiles>) {
|
||||
viewModel.updateSortData(list)
|
||||
startActivity(
|
||||
Intent(
|
||||
this@ScanResultDisplayActivity,
|
||||
PhotoSortingActivity::class.java
|
||||
SortingActivity::class.java
|
||||
).apply {
|
||||
putExtra(KEY_SCAN_TYPE, scanType)
|
||||
putParcelableArrayListExtra(
|
||||
PhotoSortingActivity.KEY_PHOTO_FOLDER_FILE,
|
||||
list
|
||||
)
|
||||
putExtra(Common.KEY_FILE_TYPE, scanType.mediaType.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -10,13 +10,14 @@ import com.ux.video.file.filerecovery.databinding.ScanResultDocumentsAdapterBind
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
/**
|
||||
* 文件或者音频的扫描结果汇总适配器
|
||||
*/
|
||||
class ScanResultDocumentsAdapter(
|
||||
class ScanResultDocumentsAudioAdapter(
|
||||
mContext: Context,
|
||||
var type: Int,
|
||||
var fileType: FileType,
|
||||
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||
) :
|
||||
BaseAdapter<ResultData, ScanResultDocumentsAdapterBinding>(mContext) {
|
||||
@ -38,13 +39,15 @@ class ScanResultDocumentsAdapter(
|
||||
relativeLayout.setOnClickListener { onClickItem(allFiles) }
|
||||
textDirName.text = dirName
|
||||
textFileCounts.text = allFiles.size.toString()
|
||||
when(type){
|
||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio->{
|
||||
when(fileType){
|
||||
FileType.AUDIO ->{
|
||||
icon.setImageResource(R.drawable.icon_folder_audio)
|
||||
}
|
||||
Common.VALUE_SCAN_TYPE_documents, Common.VALUE_SCAN_TYPE_deleted_documents->{
|
||||
FileType.DOCUMENT->{
|
||||
icon.setImageResource(R.drawable.icon_folder_documents)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.ux.video.file.filerecovery.result
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
@ -9,16 +10,23 @@ import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseAdapter
|
||||
import com.ux.video.file.filerecovery.databinding.ScanResultAdapterBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.targetFile
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||
import java.io.File
|
||||
|
||||
class ScanResultPhotoAdapter(
|
||||
/**
|
||||
* 图片或者视频的扫描结果汇总适配器
|
||||
*/
|
||||
class ScanResultPhotoVideoAdapter(
|
||||
mContext: Context,
|
||||
var type: Int,
|
||||
var fileType: FileType,
|
||||
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||
) :
|
||||
BaseAdapter<ResultData, ScanResultAdapterBinding>(mContext) {
|
||||
@ -45,7 +53,7 @@ class ScanResultPhotoAdapter(
|
||||
val takeFiles = allFiles.take(3)
|
||||
imageViews.forEachIndexed { index, imageView ->
|
||||
if (index < takeFiles.size) {
|
||||
takeFiles[index].targetFile?.let {
|
||||
takeFiles[index].targetFile().let {
|
||||
loadImageView(mContext, it, imageView)
|
||||
}
|
||||
} else {
|
||||
@ -61,12 +69,17 @@ class ScanResultPhotoAdapter(
|
||||
}
|
||||
|
||||
private fun loadImageView(context: Context, file: File, imageView: ImageView) {
|
||||
ScanManager.showLog(
|
||||
"加载图片",
|
||||
"-----loadImageView--path = ${file.path}"
|
||||
)
|
||||
Glide.with(context)
|
||||
.load(file)
|
||||
.apply(
|
||||
RequestOptions()
|
||||
.transform(CenterCrop(), RoundedCorners(8.dpToPx(context)))
|
||||
)
|
||||
.error(R.drawable.photo_place_holder)
|
||||
.into(imageView)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.ux.video.file.filerecovery.result
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
|
||||
object ScanResultRepository {
|
||||
|
||||
|
||||
//扫描数据
|
||||
val scanData = MutableLiveData<List<ResultData>>()
|
||||
|
||||
|
||||
//扫描用于排序显示的数据
|
||||
val sortingData = MutableLiveData<List<ResultDataFiles>>()
|
||||
|
||||
fun setScanResult(data: List<ResultData>) {
|
||||
scanData.postValue(data)
|
||||
}
|
||||
|
||||
fun setSortResult(data: List<ResultDataFiles>) {
|
||||
sortingData.postValue(data)
|
||||
}
|
||||
}
|
||||
@ -4,103 +4,83 @@ import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Environment
|
||||
import android.view.LayoutInflater
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
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.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.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
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 com.ux.video.file.filerecovery.utils.ScanType
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
|
||||
class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
||||
|
||||
|
||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||
private val viewModel: ScanningActivityViewModel by viewModels()
|
||||
private lateinit var scanType: ScanType
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityScanningBinding =
|
||||
ActivityScanningBinding.inflate(inflater)
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||
val typeValue = intent.getIntExtra(Common.KEY_SCAN_TYPE, ScanType.ALL_PHOTO.value)
|
||||
scanType = ScanType.from(typeValue)!!
|
||||
setSelectType(scanType)
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_documents -> scanAll()
|
||||
VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_deleted_video, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_deleted_documents -> scanDeleted()
|
||||
if (scanType.isDeletedScan) {
|
||||
scanDeleted()
|
||||
} else {
|
||||
scanAll()
|
||||
}
|
||||
|
||||
binding.imageViewBack.setOnClickListener { finish() }
|
||||
|
||||
}
|
||||
|
||||
private fun setSelectType(fileType: Int) {
|
||||
private fun setSelectType(scanType: ScanType) {
|
||||
binding.run {
|
||||
|
||||
when (fileType) {
|
||||
VALUE_SCAN_TYPE_photo -> {
|
||||
when (scanType.mediaType) {
|
||||
FileType.PHOTO->{
|
||||
title.text = getString(R.string.photo_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_photos)
|
||||
scanProgress.setCenterImage(R.drawable.im_photo_center_image)
|
||||
if(scanType.isDeletedScan){
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_photos)
|
||||
}else{
|
||||
tvScanDescribe.text = getString(R.string.describe_photos)
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
title.text = getString(R.string.photo_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_photos)
|
||||
scanProgress.setCenterImage(R.drawable.im_photo_center_image)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video -> {
|
||||
FileType.VIDEO->{
|
||||
title.text = getString(R.string.video_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_videos)
|
||||
scanProgress.setCenterImage(R.drawable.im_video_center_image)
|
||||
if(scanType.isDeletedScan){
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_videos)
|
||||
}else{
|
||||
tvScanDescribe.text = getString(R.string.describe_videos)
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_video -> {
|
||||
title.text = getString(R.string.video_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_videos)
|
||||
scanProgress.setCenterImage(R.drawable.im_video_center_image)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio -> {
|
||||
FileType.AUDIO->{
|
||||
title.text = getString(R.string.audio_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_audios)
|
||||
scanProgress.setCenterImage(R.drawable.im_audio_center_image)
|
||||
if(scanType.isDeletedScan){
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_audios)
|
||||
}else{
|
||||
tvScanDescribe.text = getString(R.string.describe_audios)
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
title.text = getString(R.string.audio_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_audios)
|
||||
scanProgress.setCenterImage(R.drawable.im_audio_center_image)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents -> {
|
||||
FileType.DOCUMENT->{
|
||||
title.text = getString(R.string.document_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_documents)
|
||||
scanProgress.setCenterImage(R.drawable.im_documents_center_image)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
title.text = getString(R.string.document_title)
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_documents)
|
||||
scanProgress.setCenterImage(R.drawable.im_documents_center_image)
|
||||
if(scanType.isDeletedScan){
|
||||
tvScanDescribe.text = getString(R.string.describe_delete_documents)
|
||||
}else{
|
||||
tvScanDescribe.text = getString(R.string.describe_documents)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,21 +93,19 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
val root = Environment.getExternalStorageDirectory()
|
||||
ScanManager.scanAllDocuments(this@ScanningActivity, root, type = scanType)
|
||||
ScanManager.scanAllDocuments(this@ScanningActivity, root, fileType = scanType.mediaType)
|
||||
.flowOn(Dispatchers.IO).collect {
|
||||
when (it) {
|
||||
is ScanState.Progress -> {
|
||||
updateProgress(it)
|
||||
}
|
||||
when (it) {
|
||||
is ScanState.Progress -> {
|
||||
updateProgress(it)
|
||||
}
|
||||
|
||||
is ScanState.Complete -> {
|
||||
updateComplete(it)
|
||||
is ScanState.Complete -> {
|
||||
updateComplete(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,19 +113,19 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
val root = Environment.getExternalStorageDirectory()
|
||||
ScanManager.scanHiddenPhotoAsync(this@ScanningActivity, root, type = scanType)
|
||||
ScanManager.scanHiddenPhotoAsync(this@ScanningActivity, root, fileType = scanType.mediaType)
|
||||
.flowOn(Dispatchers.IO).collect {
|
||||
when (it) {
|
||||
is ScanState.Progress -> {
|
||||
updateProgress(it)
|
||||
when (it) {
|
||||
is ScanState.Progress -> {
|
||||
updateProgress(it)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
is ScanState.Complete -> {
|
||||
updateComplete(it)
|
||||
is ScanState.Complete -> {
|
||||
updateComplete(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -182,18 +160,19 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
||||
if (size == 0) {
|
||||
tvScanDescribe.text.let {
|
||||
tvEmptyTypeFile.text = "0 $it"
|
||||
tvSorry.text = getString(R.string.not_found,it)
|
||||
tvSorry.text = getString(R.string.not_found, it)
|
||||
}
|
||||
relativeScanFinishedEmpty.isVisible = true
|
||||
linearCounts.isVisible = false
|
||||
}else{
|
||||
} else {
|
||||
finish()
|
||||
startActivity(Intent(this@ScanningActivity, ScanResultDisplayActivity::class.java).apply {
|
||||
putParcelableArrayListExtra(
|
||||
ScanResultDisplayActivity.KEY_SCAN_RESULT,
|
||||
it.result
|
||||
)
|
||||
putExtra(KEY_SCAN_TYPE, scanType)
|
||||
viewModel.updateData(it.result)
|
||||
startActivity(
|
||||
Intent(
|
||||
this@ScanningActivity,
|
||||
ScanResultDisplayActivity::class.java
|
||||
).apply {
|
||||
putExtra(Common.KEY_SCAN_TYPE, scanType.value)
|
||||
})
|
||||
}
|
||||
ScanManager.showLog("HiddenScan", "完成: ${it.result.size}")
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package com.ux.video.file.filerecovery.result
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
|
||||
class ScanningActivityViewModel : ViewModel() {
|
||||
|
||||
|
||||
val scanData: MutableLiveData<List<ResultData>> = ScanResultRepository.scanData
|
||||
|
||||
fun updateData(data: List<ResultData>) {
|
||||
ScanResultRepository.setScanResult(data)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.ux.video.file.filerecovery.result
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
|
||||
class ScanningResultDisplayViewModel : ViewModel() {
|
||||
|
||||
|
||||
val scanData: MutableLiveData<List<ResultData>> = ScanResultRepository.scanData
|
||||
|
||||
fun updateData(data: List<ResultData>) {
|
||||
ScanResultRepository.setScanResult(data)
|
||||
}
|
||||
fun updateSortData(data: List<ResultDataFiles>) {
|
||||
ScanResultRepository.setSortResult(data)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.ux.video.file.filerecovery.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityPrivacyPolicyBinding
|
||||
import androidx.core.net.toUri
|
||||
|
||||
class PrivacyPolicyActivity : BaseActivity<ActivityPrivacyPolicyBinding>() {
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityPrivacyPolicyBinding =
|
||||
ActivityPrivacyPolicyBinding.inflate(layoutInflater)
|
||||
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.ux.video.file.filerecovery.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.core.net.toUri
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivitySetUpBinding
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
|
||||
class SetupActivity : BaseActivity<ActivitySetUpBinding>() {
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivitySetUpBinding = ActivitySetUpBinding.inflate(layoutInflater)
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
binding.run {
|
||||
imageViewBack.setOnClickListener { finish() }
|
||||
layoutShareApp.setOnClickListener {
|
||||
Common.shareApp(this@SetupActivity)
|
||||
}
|
||||
layoutPrivacyPolicy.setOnClickListener {
|
||||
openWebPage(this@SetupActivity,getString(R.string.privacy_policy_url ))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun openWebPage(context: Context, url: String) {
|
||||
val customTabsIntent = CustomTabsIntent.Builder()
|
||||
.setShowTitle(true)
|
||||
.build()
|
||||
|
||||
customTabsIntent.launchUrl(context, url.toUri())
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,252 +0,0 @@
|
||||
package com.ux.video.file.filerecovery.sort
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
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.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.success.RecoverySuccessActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
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.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.video.PlayMediaManager
|
||||
import com.ux.video.file.filerecovery.video.VideoPlayActivity
|
||||
import java.io.File
|
||||
|
||||
class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
|
||||
|
||||
companion object {
|
||||
val KEY_CLICK_ITEM = "click_item"
|
||||
}
|
||||
|
||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||
private var myData: ResultDataFiles? = 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, ResultDataFiles::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
intent.getParcelableExtra(KEY_CLICK_ITEM)
|
||||
}
|
||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||
setView()
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
binding.run {
|
||||
imageViewBack.setOnClickListener { finish() }
|
||||
myData?.let { resultPhotosFiles ->
|
||||
|
||||
tvName.text = resultPhotosFiles.name
|
||||
tvPath.text = resultPhotosFiles.path
|
||||
tvSize.text = resultPhotosFiles.sizeString
|
||||
tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified)
|
||||
tvResolution.text = resultPhotosFiles.resolution
|
||||
tvDuration.text = Common.formatDuration(resultPhotosFiles.duration)
|
||||
resultPhotosFiles.targetFile?.let {
|
||||
tvType.text = Common.getMimeTypeParts(it)
|
||||
}
|
||||
layoutBottom.tvLeft.run {
|
||||
text = resources.getString(R.string.delete)
|
||||
setOnClickListener {
|
||||
RecoverOrDeleteManager.showConfirmDeleteDialog(
|
||||
true,
|
||||
supportFragmentManager,
|
||||
lifecycleScope,
|
||||
setOf(resultPhotosFiles)
|
||||
) { count ->
|
||||
complete(count, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
layoutBottom.tvRight.run {
|
||||
text = resources.getString(R.string.recover)
|
||||
setOnClickListener {
|
||||
RecoverOrDeleteManager.showRecoveringDialog(
|
||||
supportFragmentManager,
|
||||
lifecycleScope,
|
||||
setOf(resultPhotosFiles)
|
||||
) { count ->
|
||||
complete(count, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setView() {
|
||||
binding.run {
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutResolution.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
frameImage.setBackgroundResource(0)
|
||||
|
||||
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
layoutSize.isVisible = false
|
||||
layoutDuration.isVisible = false
|
||||
|
||||
imPlay.isVisible = false
|
||||
|
||||
myData?.targetFile?.let { loadImage(image,it) }
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutResolution.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
layoutDuration.isVisible = true
|
||||
frameImage.setBackgroundResource(0)
|
||||
|
||||
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
layoutSize.isVisible = false
|
||||
|
||||
imPlay.isVisible = true
|
||||
myData?.let { data->
|
||||
data.targetFile?.let { loadImage(image,it) }
|
||||
frameImage.setOnClickListener {
|
||||
startActivity(Intent(this@PhotoInfoActivity, VideoPlayActivity::class.java).apply {
|
||||
putExtra(VideoPlayActivity.KEY_DATA, data)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
Common.showLog("----------音频")
|
||||
layoutName.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutSize.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
layoutDuration.isVisible = true
|
||||
layoutSeekbar.isVisible = true
|
||||
imPlay.isVisible = true
|
||||
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
||||
|
||||
loadCenterImage(image,R.drawable.image_info_music)
|
||||
|
||||
initPlayAudio()
|
||||
layoutResolution.isVisible = false
|
||||
layoutType.isVisible = false
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
layoutName.isVisible = true
|
||||
layoutType.isVisible = true
|
||||
layoutPath.isVisible = true
|
||||
layoutSize.isVisible = true
|
||||
layoutDate.isVisible = true
|
||||
|
||||
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
||||
myData?.targetFile?.let {
|
||||
loadCenterImage(image, Common.getFileIconRes(it))
|
||||
}
|
||||
imPlay.isVisible = false
|
||||
layoutSeekbar.isVisible = false
|
||||
layoutResolution.isVisible = false
|
||||
layoutDuration.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCenterImage(image: ImageView,drawableId: Int){
|
||||
image.setImageResource(drawableId)
|
||||
val params = image.layoutParams ?: ViewGroup.LayoutParams(
|
||||
180.dpToPx(this@PhotoInfoActivity),
|
||||
180.dpToPx(this@PhotoInfoActivity)
|
||||
)
|
||||
params.width = 180.dpToPx(this@PhotoInfoActivity)
|
||||
params.height = 180.dpToPx(this@PhotoInfoActivity)
|
||||
image.layoutParams = params
|
||||
}
|
||||
private fun loadImage(image: ImageView,file: File){
|
||||
Glide.with(this@PhotoInfoActivity)
|
||||
.load(file)
|
||||
.apply(RequestOptions().transform(CenterCrop(), RoundedCorners(8.dpToPx(this@PhotoInfoActivity))))
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable?>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
model: Any,
|
||||
target: Target<Drawable?>?,
|
||||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
})
|
||||
.into(image)
|
||||
}
|
||||
|
||||
|
||||
private fun initPlayAudio(){
|
||||
myData?.targetFile?.let {
|
||||
binding.run {
|
||||
PlayMediaManager(context = this@PhotoInfoActivity, mediaFile = it,
|
||||
seekBar = seekBar, playBtn = imPlay, onUpdateProgress = { current,total->
|
||||
textTimeCurrent.text = current
|
||||
textTimeTotal.text = total
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun complete(number: Int, type: Int) {
|
||||
finish()
|
||||
startActivity(Intent(this@PhotoInfoActivity, RecoverySuccessActivity::class.java).apply {
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_COUNT, number)
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ import com.ux.video.file.filerecovery.databinding.DialogSortBinding
|
||||
class SortDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFragment() {
|
||||
|
||||
private lateinit var binding: DialogSortBinding
|
||||
private var clickType = PhotoSortingActivity.SORT_DESC_DATE
|
||||
private var clickType = SortingActivity.SORT_DESC_DATE
|
||||
|
||||
private lateinit var LayoutList: List<CommonLayoutSortItemBinding>
|
||||
override fun onStart() {
|
||||
|
||||
@ -10,22 +10,22 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.ux.video.file.filerecovery.base.BaseAdapter
|
||||
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
|
||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
|
||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
||||
import com.ux.video.file.filerecovery.db.isThumbnail
|
||||
|
||||
class PhotoDisplayDateAdapter(
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
/**
|
||||
* 排序页面显示
|
||||
*/
|
||||
class SortDisplayAdapter(
|
||||
mContext: Context,
|
||||
var scanType: Int,
|
||||
var fileType: FileType,
|
||||
var mColumns: Int,
|
||||
var viewModel: ScanRepository,
|
||||
var viewModel: SortingViewModel,
|
||||
var onSelectedUpdate: (resultDataFiles: ResultDataFiles, isAdd: Boolean) -> Unit,
|
||||
var clickItem: (item: ResultDataFiles) -> Unit
|
||||
) :
|
||||
BaseAdapter<Pair<String, List<ResultDataFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
|
||||
|
||||
|
||||
private var allSelected: Boolean? = null
|
||||
|
||||
override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateAdapterBinding =
|
||||
@ -41,7 +41,7 @@ class PhotoDisplayDateAdapter(
|
||||
*/
|
||||
fun getTotalChildCount(hideThumbnails: Boolean): Int {
|
||||
if (hideThumbnails) {
|
||||
return data.sumOf { it.second.filter { !it.isThumbnail }.size }
|
||||
return data.sumOf { it.second.filter { !it.isThumbnail() }.size }
|
||||
} else {
|
||||
return data.sumOf { it.second.size }
|
||||
}
|
||||
@ -80,9 +80,9 @@ class PhotoDisplayDateAdapter(
|
||||
holder.vb.run {
|
||||
item.run {
|
||||
val (date, files) = item
|
||||
val childAdapter = PhotoDisplayDateChildAdapter(
|
||||
val childAdapter = SortDisplayChildAdapter(
|
||||
mContext,
|
||||
scanType,
|
||||
fileType,
|
||||
mColumns,
|
||||
viewModel,
|
||||
{ resultPhotosFiles, addOrRemove, isDateAllSelected ->
|
||||
@ -108,8 +108,8 @@ class PhotoDisplayDateAdapter(
|
||||
textChildCounts.text = "(${files.size})"
|
||||
|
||||
recyclerChild.apply {
|
||||
layoutManager = when (scanType) {
|
||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
layoutManager = when (fileType) {
|
||||
FileType.AUDIO, FileType.DOCUMENT -> {
|
||||
LinearLayoutManager(context)
|
||||
}
|
||||
|
||||
@ -25,16 +25,22 @@ import com.ux.video.file.filerecovery.databinding.FileSpanCountTwoAdapterBinding
|
||||
import com.ux.video.file.filerecovery.databinding.OneAudioItemBinding
|
||||
import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.duration
|
||||
import com.ux.video.file.filerecovery.db.targetFile
|
||||
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
||||
|
||||
class PhotoDisplayDateChildAdapter(
|
||||
|
||||
/**
|
||||
* 排序页面显示 、已经恢复的文件页面显示
|
||||
*/
|
||||
class SortDisplayChildAdapter(
|
||||
mContext: Context,
|
||||
var scanType: Int,
|
||||
var fileType: FileType,
|
||||
var mColumns: Int,
|
||||
var viewModel: ViewModel? = null,
|
||||
/**
|
||||
@ -72,12 +78,12 @@ class PhotoDisplayDateChildAdapter(
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
when (scanType) {
|
||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
when (fileType) {
|
||||
FileType.AUDIO -> {
|
||||
return TYPE_AUDIO
|
||||
}
|
||||
|
||||
Common.VALUE_SCAN_TYPE_documents, Common.VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
FileType.DOCUMENT -> {
|
||||
return TYPE_DOCUMENTS
|
||||
}
|
||||
|
||||
@ -172,20 +178,10 @@ class PhotoDisplayDateChildAdapter(
|
||||
item.run {
|
||||
holder.vb.let {
|
||||
it.textName.text = name
|
||||
it.textDuration.text = Common.formatDuration(duration)
|
||||
it.textDuration.text = Common.formatDuration(duration())
|
||||
it.textSize.text = sizeString
|
||||
|
||||
initAudioDocuments(it.imageSelect, this)
|
||||
// viewModel.checkIsSelect(this).let { isSelected ->
|
||||
// it.imageSelect.isSelected = isSelected
|
||||
// addOrRemove(this, isSelected)
|
||||
// }
|
||||
// it.imageSelect.setOnClickListener {
|
||||
// it.isSelected = !it.isSelected
|
||||
// it.isSelected.let { newStatus ->
|
||||
// addOrRemove(this, newStatus)
|
||||
// }
|
||||
// }
|
||||
it.constraintLayout.setOnClickListener {
|
||||
clickItem(this)
|
||||
}
|
||||
@ -200,7 +196,7 @@ class PhotoDisplayDateChildAdapter(
|
||||
it.textName.text = name
|
||||
it.textDate.text = Common.getItemMonthDay(lastModified)
|
||||
it.textSize.text = sizeString
|
||||
targetFile?.let { file ->
|
||||
targetFile().let { file ->
|
||||
it.imageIcon.setImageResource(Common.getFileIconRes(file))
|
||||
}
|
||||
|
||||
@ -235,11 +231,11 @@ class PhotoDisplayDateChildAdapter(
|
||||
private fun initAudioDocuments(imageSelect: ImageView, item: ResultDataFiles) {
|
||||
|
||||
viewModel?.let {
|
||||
if (it is ScanRepository) {
|
||||
if (it is SortingViewModel) {
|
||||
it.checkIsSelect(item)
|
||||
} else {
|
||||
it as RecoveryPhotoViewModel
|
||||
it.checkIsSelect(item)
|
||||
it.checkIsSelect(fileType, item)
|
||||
}.let { isSelected ->
|
||||
imageSelect.isSelected = isSelected == true
|
||||
addOrRemove(item, isSelected == true)
|
||||
@ -265,31 +261,21 @@ class PhotoDisplayDateChildAdapter(
|
||||
) {
|
||||
item.run {
|
||||
initAudioDocuments(imageSelectStatus, this)
|
||||
// viewModel.checkIsSelect(this).let {
|
||||
// imageSelectStatus.isSelected = it
|
||||
// addOrRemove(this, it)
|
||||
// }
|
||||
// imageSelectStatus.setOnClickListener {
|
||||
// it.isSelected = !it.isSelected
|
||||
// it.isSelected.let { newStatus ->
|
||||
// addOrRemove(this, newStatus)
|
||||
// }
|
||||
// }
|
||||
textSize.text = sizeString
|
||||
|
||||
imageType.setImageResource(
|
||||
when (scanType) {
|
||||
Common.VALUE_SCAN_TYPE_photo, Common.VALUE_SCAN_TYPE_deleted_photo -> R.drawable.icon_type_photo
|
||||
Common.VALUE_SCAN_TYPE_video, Common.VALUE_SCAN_TYPE_deleted_video -> R.drawable.icon_type_video
|
||||
when (fileType) {
|
||||
FileType.PHOTO -> R.drawable.icon_type_photo
|
||||
FileType.VIDEO -> R.drawable.icon_type_video
|
||||
else -> R.drawable.icon_type_photo
|
||||
}
|
||||
)
|
||||
Glide.with(mContext)
|
||||
.load(targetFile)
|
||||
.load(targetFile())
|
||||
.apply(
|
||||
RequestOptions()
|
||||
.transform(CenterCrop(), RoundedCorners(8.dpToPx(mContext)))
|
||||
)
|
||||
.error(R.drawable.photo_place_holder)
|
||||
.listener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
@ -299,7 +285,7 @@ class PhotoDisplayDateChildAdapter(
|
||||
): Boolean {
|
||||
ScanManager.showLog(
|
||||
"加载图片",
|
||||
"-------path = ${path} file=${targetFile}"
|
||||
"-------path = ${path} e=${e?.message}"
|
||||
)
|
||||
return false
|
||||
}
|
||||
@ -6,8 +6,8 @@ import android.text.TextWatcher
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -15,17 +15,10 @@ 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.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.isThumbnail
|
||||
import com.ux.video.file.filerecovery.detail.DetailsActivity
|
||||
import com.ux.video.file.filerecovery.success.RecoverySuccessActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
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.Common.setItemSelect
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterByDuration
|
||||
@ -36,19 +29,19 @@ import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterRemoveThumbnai
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterThumbnailsAsync
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinDateRange
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinDateRangeList
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.getParcelableArrayListExtraCompat
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.kbToBytes
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.mbToBytes
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.minutesToMillisecond
|
||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.removeItem
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration
|
||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
||||
import com.ux.video.file.filerecovery.utils.ScanType
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
|
||||
class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
class SortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
companion object {
|
||||
//指定文件夹下的所有文件
|
||||
@ -67,14 +60,14 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
val SORT_DESC_DATE = 3
|
||||
}
|
||||
|
||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||
private lateinit var fileType: FileType
|
||||
|
||||
private var sortDialogFragment: SortDialogFragment? = null
|
||||
private var columns = 3
|
||||
private var dateAdapter: PhotoDisplayDateAdapter? = null
|
||||
private var dateAdapter: SortDisplayAdapter? = null
|
||||
|
||||
//文件大小排序使用的适配器
|
||||
private var sizeSortAdapter: PhotoDisplayDateChildAdapter? = null
|
||||
private var sizeSortAdapter: SortDisplayChildAdapter? = null
|
||||
|
||||
|
||||
private var dialogCustomerDateStart: DatePickerDialogFragment? = null
|
||||
@ -118,20 +111,86 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
private lateinit var sizeFilterItemArray: Array<String>
|
||||
|
||||
private val viewModel: SortingViewModel by viewModels()
|
||||
private lateinit var list: List<ResultDataFiles>
|
||||
|
||||
// private lateinit var viewModel: SortingViewModel
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoSortingBinding {
|
||||
|
||||
return ActivityPhotoSortingBinding.inflate(inflater)
|
||||
}
|
||||
|
||||
private lateinit var viewModel: ScanRepository
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoSortingBinding =
|
||||
ActivityPhotoSortingBinding.inflate(inflater)
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||
val list: ArrayList<ResultDataFiles>? =
|
||||
intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE)
|
||||
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||
|
||||
fileType = FileType.from(intExtra)!!
|
||||
mItemDecoration =
|
||||
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
|
||||
updateButtonCounts(0)
|
||||
viewModel = ViewModelProvider(this)[ScanRepository::class.java]
|
||||
viewModel.sortingData.observe(this) { sortData ->
|
||||
list = sortData
|
||||
|
||||
list.let {
|
||||
binding.tvThumbnailCounts.text =
|
||||
getString(R.string.hide_thumbnails, it.filter { it.isThumbnail() }.size)
|
||||
|
||||
//降序(最近的在前面)
|
||||
sortByDateReverse = Common.getSortByDayNewToOldInit(it)
|
||||
//升序(时间最远的在前面)
|
||||
sortedByDatePositive = Common.getSortByDayOldToNew(sortByDateReverse)
|
||||
sortBySizeBigToSmall = Common.getSortBySizeBigToSmall(it)
|
||||
sortBySizeSmallToBig = Common.getSortBySizeSmallToBig(it)
|
||||
|
||||
sizeSortAdapter = SortDisplayChildAdapter(
|
||||
this@SortingActivity,
|
||||
fileType,
|
||||
columns, viewModel,
|
||||
{ resultPhotosFiles, isAdd, allSelected ->
|
||||
viewModel.toggleSelection(isAdd, resultPhotosFiles)
|
||||
}, { hide ->
|
||||
|
||||
|
||||
}) { item ->
|
||||
startActivity(
|
||||
Intent(
|
||||
this@SortingActivity,
|
||||
DetailsActivity::class.java
|
||||
).apply {
|
||||
putExtra(Common.KEY_FILE_TYPE, item.fileType.value)
|
||||
putExtra(DetailsActivity.KEY_CLICK_ITEM, item)
|
||||
})
|
||||
|
||||
}
|
||||
dateAdapter =
|
||||
SortDisplayAdapter(
|
||||
this@SortingActivity,
|
||||
fileType,
|
||||
columns,
|
||||
viewModel,
|
||||
{ actionPath, isAdd ->
|
||||
viewModel.toggleSelection(isAdd, actionPath)
|
||||
}) { item ->
|
||||
startActivity(
|
||||
Intent(
|
||||
this@SortingActivity,
|
||||
DetailsActivity::class.java
|
||||
).apply {
|
||||
putExtra(Common.KEY_FILE_TYPE, fileType.value)
|
||||
putExtra(DetailsActivity.KEY_CLICK_ITEM, item)
|
||||
})
|
||||
}.apply {
|
||||
setData(sortByDateReverse)
|
||||
resetCurrentDateList(sortByDateReverse)
|
||||
}
|
||||
setDateAdapter()
|
||||
setSingleDelete()
|
||||
setFilter()
|
||||
setAllClick()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.selectedLiveData.observe(this) { selectedSet ->
|
||||
allSelectedSetList = selectedSet
|
||||
@ -144,64 +203,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
updateCurrentIsAllSelectStatus()
|
||||
}
|
||||
setScanTypeView()
|
||||
list?.let {
|
||||
binding.tvThumbnailCounts.text =
|
||||
getString(R.string.hide_thumbnails, it.filter { it.isThumbnail }.size)
|
||||
|
||||
//降序(最近的在前面)
|
||||
sortByDateReverse = Common.getSortByDayNewToOldInit(it)
|
||||
//升序(时间最远的在前面)
|
||||
sortedByDatePositive = Common.getSortByDayOldToNew(sortByDateReverse)
|
||||
sortBySizeBigToSmall = Common.getSortBySizeBigToSmall(it)
|
||||
sortBySizeSmallToBig = Common.getSortBySizeSmallToBig(it)
|
||||
|
||||
sizeSortAdapter = PhotoDisplayDateChildAdapter(
|
||||
this@PhotoSortingActivity,
|
||||
scanType,
|
||||
columns, viewModel,
|
||||
{ resultPhotosFiles, isAdd, allSelected ->
|
||||
viewModel.toggleSelection(isAdd, resultPhotosFiles)
|
||||
}, { hide ->
|
||||
|
||||
|
||||
}) { item ->
|
||||
startActivity(
|
||||
Intent(
|
||||
this@PhotoSortingActivity,
|
||||
PhotoInfoActivity::class.java
|
||||
).apply {
|
||||
putExtra(KEY_SCAN_TYPE, scanType)
|
||||
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
|
||||
})
|
||||
|
||||
}
|
||||
dateAdapter =
|
||||
PhotoDisplayDateAdapter(
|
||||
this@PhotoSortingActivity,
|
||||
scanType,
|
||||
columns,
|
||||
viewModel,
|
||||
{ actionPath, isAdd ->
|
||||
viewModel.toggleSelection(isAdd, actionPath)
|
||||
}) { item ->
|
||||
startActivity(
|
||||
Intent(
|
||||
this@PhotoSortingActivity,
|
||||
PhotoInfoActivity::class.java
|
||||
).apply {
|
||||
putExtra(KEY_SCAN_TYPE, scanType)
|
||||
putExtra(PhotoInfoActivity.KEY_CLICK_ITEM, item)
|
||||
})
|
||||
}.apply {
|
||||
setData(sortByDateReverse)
|
||||
resetCurrentDateList(sortByDateReverse)
|
||||
}
|
||||
setDateAdapter()
|
||||
setSingleDelete()
|
||||
setFilter()
|
||||
setAllClick()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -210,7 +212,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
imageViewBack.setOnClickListener { finish() }
|
||||
switchHideThumbnails.setOnCheckedChangeListener { _, isChecked ->
|
||||
when (recyclerView.adapter) {
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
is SortDisplayAdapter -> {
|
||||
lifecycleScope.launch {
|
||||
dateAdapter?.run {
|
||||
initGetCurrentDateList().let { list ->
|
||||
@ -225,7 +227,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
}
|
||||
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
is SortDisplayChildAdapter -> {
|
||||
lifecycleScope.launch {
|
||||
sizeSortAdapter?.run {
|
||||
initGetCurrentSizeList().let {
|
||||
@ -336,7 +338,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
tvSelectAll.setOnClickListener {
|
||||
it.isSelected = !it.isSelected
|
||||
when (binding.recyclerView.adapter) {
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
is SortDisplayAdapter -> {
|
||||
dateAdapter?.setAllSelected(it.isSelected)
|
||||
dateAdapter?.getCurrentData()?.let {
|
||||
it as List<Pair<String, List<ResultDataFiles>>>
|
||||
@ -346,7 +348,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
}
|
||||
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
is SortDisplayChildAdapter -> {
|
||||
sizeSortAdapter?.setAllSelected(it.isSelected)
|
||||
sizeSortAdapter?.getCurrentData()?.let {
|
||||
it as List<ResultDataFiles>
|
||||
@ -367,43 +369,47 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
*/
|
||||
private fun setScanTypeView() {
|
||||
binding.run {
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
titleSize.text = getString(R.string.size)
|
||||
filterLayoutLinearlayout.isVisible = true
|
||||
relativeThumbnails.isVisible = true
|
||||
layoutSearch.isVisible = false
|
||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_size_photo)
|
||||
}
|
||||
fileType?.let {
|
||||
when (it) {
|
||||
FileType.PHOTO -> {
|
||||
titleSize.text = getString(R.string.size)
|
||||
filterLayoutLinearlayout.isVisible = true
|
||||
relativeThumbnails.isVisible = true
|
||||
layoutSearch.isVisible = false
|
||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_size_photo)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
|
||||
titleSize.text = getString(R.string.duration)
|
||||
filterLayoutLinearlayout.isVisible = true
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = false
|
||||
sizeFilterItemArray =
|
||||
resources.getStringArray(R.array.filter_duration_video_audio)
|
||||
}
|
||||
FileType.VIDEO -> {
|
||||
titleSize.text = getString(R.string.duration)
|
||||
filterLayoutLinearlayout.isVisible = true
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = false
|
||||
sizeFilterItemArray =
|
||||
resources.getStringArray(R.array.filter_duration_video_audio)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
titleSize.text = getString(R.string.duration)
|
||||
filterLayoutLinearlayout.isVisible = false
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = true
|
||||
sizeFilterItemArray =
|
||||
resources.getStringArray(R.array.filter_duration_video_audio)
|
||||
initSearch()
|
||||
}
|
||||
FileType.AUDIO -> {
|
||||
titleSize.text = getString(R.string.duration)
|
||||
filterLayoutLinearlayout.isVisible = false
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = true
|
||||
sizeFilterItemArray =
|
||||
resources.getStringArray(R.array.filter_duration_video_audio)
|
||||
initSearch()
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
titleSize.text = getString(R.string.size)
|
||||
filterLayoutLinearlayout.isVisible = false
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = true
|
||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_documents_size)
|
||||
initSearch()
|
||||
}
|
||||
}
|
||||
FileType.DOCUMENT -> {
|
||||
titleSize.text = getString(R.string.size)
|
||||
filterLayoutLinearlayout.isVisible = false
|
||||
relativeThumbnails.isVisible = false
|
||||
layoutSearch.isVisible = true
|
||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_documents_size)
|
||||
initSearch()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -413,8 +419,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
binding.tvSelectCounts.text = it.toString()
|
||||
updateButtonCounts(it)
|
||||
when (binding.recyclerView.adapter) {
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
val adapter = binding.recyclerView.adapter as PhotoDisplayDateAdapter
|
||||
is SortDisplayAdapter -> {
|
||||
val adapter = binding.recyclerView.adapter as SortDisplayAdapter
|
||||
if (it > 0) {
|
||||
binding.tvSelectAll.isSelected = it == adapter.getTotalChildCount(false)
|
||||
} else {
|
||||
@ -423,8 +429,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
}
|
||||
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
val adapter = binding.recyclerView.adapter as PhotoDisplayDateChildAdapter
|
||||
is SortDisplayChildAdapter -> {
|
||||
val adapter = binding.recyclerView.adapter as SortDisplayChildAdapter
|
||||
if (it > 0) {
|
||||
binding.tvSelectAll.isSelected =
|
||||
it == adapter.itemCount
|
||||
@ -448,7 +454,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
currentDateList = null
|
||||
|
||||
binding.tvThumbnailCounts.text =
|
||||
getString(R.string.hide_thumbnails, currentList.filter { it.isThumbnail }.size)
|
||||
getString(R.string.hide_thumbnails, currentList.filter { it.isThumbnail() }.size)
|
||||
|
||||
}
|
||||
|
||||
@ -461,7 +467,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
currentDateList = currentList
|
||||
currentSizeList = null
|
||||
val totalSelectedCount = currentList.sumOf { pair ->
|
||||
pair.second.filter { it.isThumbnail }.size
|
||||
pair.second.filter { it.isThumbnail() }.size
|
||||
}
|
||||
binding.tvThumbnailCounts.text =
|
||||
getString(R.string.hide_thumbnails, totalSelectedCount)
|
||||
@ -474,7 +480,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
private fun setDateAdapter() {
|
||||
binding.recyclerView.run {
|
||||
adapter = dateAdapter?.apply { setColumns(columns) }
|
||||
layoutManager = LinearLayoutManager(this@PhotoSortingActivity)
|
||||
layoutManager = LinearLayoutManager(this@SortingActivity)
|
||||
setPadding(0, 0, 0, 70.dpToPx(context))
|
||||
clipToPadding = false
|
||||
}
|
||||
@ -484,8 +490,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
binding.recyclerView.run {
|
||||
val aPx = 16.dpToPx(context)
|
||||
val bottom = 70.dpToPx(context)
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio,VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
when (fileType) {
|
||||
FileType.AUDIO, FileType.DOCUMENT-> {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
setPadding(aPx, 0, 0, bottom)
|
||||
}
|
||||
@ -513,7 +519,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
setItemSelect(it as LinearLayout, true)
|
||||
resources.getStringArray(R.array.filter_date).let { data ->
|
||||
filterDatePopupWindows = filterDatePopupWindows ?: DateFilterPopupWindows(
|
||||
this@PhotoSortingActivity,
|
||||
this@SortingActivity,
|
||||
0,
|
||||
{ clickValue, showDialog ->
|
||||
when (clickValue) {
|
||||
@ -576,7 +582,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
setItemSelect(it as LinearLayout, true)
|
||||
sizeFilterItemArray.let { data ->
|
||||
filterSizePopupWindows = filterSizePopupWindows ?: FilterPopupWindows(
|
||||
this@PhotoSortingActivity,
|
||||
this@SortingActivity,
|
||||
data,
|
||||
0,
|
||||
{ clickValue ->
|
||||
@ -598,7 +604,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
setItemSelect(it as LinearLayout, true)
|
||||
resources.getStringArray(R.array.filter_layout).let { data ->
|
||||
filterLayoutPopupWindows = filterLayoutPopupWindows ?: FilterPopupWindows(
|
||||
this@PhotoSortingActivity,
|
||||
this@SortingActivity,
|
||||
data,
|
||||
1,
|
||||
{ clickValue ->
|
||||
@ -608,13 +614,13 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
data[2] -> columns = 4
|
||||
}
|
||||
when (binding.recyclerView.adapter) {
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
is SortDisplayAdapter -> {
|
||||
dateAdapter?.setColumns(columns)
|
||||
}
|
||||
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
is SortDisplayChildAdapter -> {
|
||||
binding.recyclerView.layoutManager =
|
||||
GridLayoutManager(this@PhotoSortingActivity, columns)
|
||||
GridLayoutManager(this@SortingActivity, columns)
|
||||
sizeSortAdapter?.setColumns(columns)
|
||||
}
|
||||
}
|
||||
@ -654,10 +660,10 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
private fun startFilter() {
|
||||
Common.showLog("--------------开始筛选")
|
||||
|
||||
val filterSizeCovert = filterSizeCovert(scanType, filterSize)
|
||||
val filterSizeCovert = filterSizeCovert(fileType, filterSize)
|
||||
when (binding.recyclerView.adapter) {
|
||||
//当前是时间排序
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
is SortDisplayAdapter -> {
|
||||
//确定当前排序
|
||||
val list = if (sortReverse) sortByDateReverse else sortedByDatePositive
|
||||
list.filterWithinDateRange(
|
||||
@ -665,8 +671,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
||||
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
||||
).run {
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
when (fileType) {
|
||||
FileType.PHOTO,FileType.DOCUMENT -> {
|
||||
filterBySize(filterSizeCovert.first, filterSizeCovert.second)
|
||||
}
|
||||
|
||||
@ -684,15 +690,15 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
}
|
||||
//当前是大小排序
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
is SortDisplayChildAdapter -> {
|
||||
val list = if (sortReverse) sortBySizeBigToSmall else sortBySizeSmallToBig
|
||||
list.filterWithinDateRangeList(
|
||||
filterDate,
|
||||
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
||||
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
||||
).run {
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
when (fileType) {
|
||||
FileType.PHOTO,FileType.DOCUMENT-> {
|
||||
filterBySizeList(filterSizeCovert.first, filterSizeCovert.second)
|
||||
}
|
||||
|
||||
@ -736,9 +742,9 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
}
|
||||
|
||||
|
||||
private fun filterSizeCovert(scanType: Int, filterSize: String): Pair<Long, Long> {
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
private fun filterSizeCovert(fileType: FileType, filterSize: String): Pair<Long, Long> {
|
||||
when (fileType) {
|
||||
FileType.PHOTO -> {
|
||||
val stringArray = resources.getStringArray(R.array.filter_size_photo)
|
||||
return when (filterSize) {
|
||||
stringArray[0] -> Pair(-1L, -1L)
|
||||
@ -749,7 +755,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video, VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
FileType.VIDEO, FileType.AUDIO -> {
|
||||
val stringArray = resources.getStringArray(R.array.filter_duration_video_audio)
|
||||
return when (filterSize) {
|
||||
stringArray[0] -> Pair(-1L, -1L)
|
||||
@ -761,7 +767,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
FileType.DOCUMENT-> {
|
||||
val stringArray = resources.getStringArray(R.array.filter_documents_size)
|
||||
return when (filterSize) {
|
||||
stringArray[0] -> Pair(-1L, -1L)
|
||||
@ -773,7 +779,6 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(-1L, -1L)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -846,9 +851,10 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
* @param type 0 恢复 1 删除
|
||||
*/
|
||||
private fun complete(number: Int, type: Int) {
|
||||
startActivity(Intent(this@PhotoSortingActivity, RecoverySuccessActivity::class.java).apply {
|
||||
startActivity(Intent(this@SortingActivity, RecoverySuccessActivity::class.java).apply {
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_COUNT, number)
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
||||
putExtra(Common.KEY_FILE_TYPE, fileType.value)
|
||||
})
|
||||
if (type == 1) {
|
||||
lifecycleScope.launch {
|
||||
@ -1019,11 +1025,11 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||
|
||||
private fun checkTypeAfter(onAction: (isDateSort: Boolean) -> Unit) {
|
||||
when (binding.recyclerView.adapter) {
|
||||
is PhotoDisplayDateAdapter -> {
|
||||
is SortDisplayAdapter -> {
|
||||
onAction(true)
|
||||
}
|
||||
|
||||
is PhotoDisplayDateChildAdapter -> {
|
||||
is SortDisplayChildAdapter -> {
|
||||
onAction(false)
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,14 @@
|
||||
package com.ux.video.file.filerecovery.utils
|
||||
package com.ux.video.file.filerecovery.sort
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.result.ScanResultRepository
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
|
||||
|
||||
class ScanRepository : ViewModel() {
|
||||
class SortingViewModel : ViewModel() {
|
||||
// private val _selectedFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
||||
// val selectedFlow: StateFlow<MutableSet<String>> = _selectedFlow
|
||||
//
|
||||
@ -14,7 +16,7 @@ class ScanRepository : ViewModel() {
|
||||
// private val _selectedDisplayFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
||||
// val selectedDisplayFlow: StateFlow<MutableSet<String>> = _selectedDisplayFlow
|
||||
|
||||
|
||||
val sortingData: MutableLiveData<List<ResultDataFiles>> = ScanResultRepository.sortingData
|
||||
|
||||
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
|
||||
@ -71,7 +73,7 @@ class ScanRepository : ViewModel() {
|
||||
/**
|
||||
* 详情页删除完毕,移除删除掉的数据(单个删除)
|
||||
*/
|
||||
fun afterSingleDeleted(deletedItem:ResultDataFiles){
|
||||
fun afterSingleDeleted(deletedItem: ResultDataFiles){
|
||||
val selected = _selectedLiveData.value.orEmpty().toMutableSet()
|
||||
val display = _selectedDisplayLiveData.value.orEmpty().toMutableSet()
|
||||
|
||||
@ -90,4 +92,4 @@ class ScanRepository : ViewModel() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,36 +1,15 @@
|
||||
package com.ux.video.file.filerecovery.success
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Environment
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.view.isVisible
|
||||
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.MainActivity
|
||||
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.recovery.RecoveryActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
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
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBinding>() {
|
||||
|
||||
@ -39,7 +18,7 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
||||
val KEY_SUCCESS_COUNT = "success_count"
|
||||
}
|
||||
|
||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||
private lateinit var fileType: FileType
|
||||
|
||||
//0 恢复成功 1 删除成功
|
||||
private var successType = 0
|
||||
@ -48,7 +27,10 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||
|
||||
fileType = FileType.from(intExtra)!!
|
||||
|
||||
successType = intent.getIntExtra(KEY_SUCCESS_TYPE, 0)
|
||||
val counts = intent.getIntExtra(KEY_SUCCESS_COUNT, 0)
|
||||
|
||||
@ -58,17 +40,17 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
||||
tvLeft.text = resources.getString(R.string.text_continue)
|
||||
tvRight.text = resources.getString(R.string.view)
|
||||
}
|
||||
when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> tvFileType.text =
|
||||
when (fileType) {
|
||||
FileType.PHOTO -> tvFileType.text =
|
||||
resources.getString(R.string.describe_photos)
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> tvFileType.text =
|
||||
FileType.VIDEO -> tvFileType.text =
|
||||
resources.getString(R.string.describe_videos)
|
||||
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> tvFileType.text =
|
||||
FileType.AUDIO -> tvFileType.text =
|
||||
resources.getString(R.string.describe_audios)
|
||||
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> tvFileType.text =
|
||||
FileType.DOCUMENT -> tvFileType.text =
|
||||
resources.getString(R.string.describe_documents)
|
||||
}
|
||||
when (successType) {
|
||||
@ -86,7 +68,13 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
||||
|
||||
bottomBtnRecoverLayout.tvLeft.setOnClickListener { finish()}
|
||||
bottomBtnRecoverLayout.tvRight.setOnClickListener {
|
||||
//todo 跳转到所有恢复文件页面
|
||||
finish()
|
||||
Intent(this@RecoverySuccessActivity,RecoveryActivity::class.java).apply {
|
||||
putExtra(Common.KEY_FILE_TYPE,fileType.value)
|
||||
}.let {
|
||||
startActivity(it)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ package com.ux.video.file.filerecovery.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.icu.util.Calendar
|
||||
import android.media.MediaMetadataRetriever
|
||||
@ -11,34 +13,24 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import com.ux.video.file.filerecovery.R
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.utils.ScanManager.getVideoResolution
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlin.collections.sortedBy
|
||||
|
||||
object Common {
|
||||
|
||||
val itemSpacing = 10
|
||||
val horizontalSpacing = 16
|
||||
|
||||
val KEY_SCAN_TYPE = "scan_type"
|
||||
val VALUE_SCAN_TYPE_photo = 0
|
||||
val VALUE_SCAN_TYPE_deleted_photo = 1
|
||||
val VALUE_SCAN_TYPE_video = 2
|
||||
val VALUE_SCAN_TYPE_deleted_video = 3
|
||||
val VALUE_SCAN_TYPE_audio = 4
|
||||
val VALUE_SCAN_TYPE_deleted_audio = 5
|
||||
val VALUE_SCAN_TYPE_documents = 6
|
||||
val VALUE_SCAN_TYPE_deleted_documents = 7
|
||||
val KEY_SCAN_TYPE = "key_scan_type"
|
||||
val KEY_FILE_TYPE = "key_file_type"
|
||||
|
||||
val FILE_TYPE_PHOTO = 0
|
||||
val FILE_TYPE_VIDEO = 1
|
||||
val FILE_TYPE_AUDIO = 2
|
||||
val FILE_TYPE_DOCUMENTS = 3
|
||||
|
||||
|
||||
|
||||
@ -103,6 +95,7 @@ object Common {
|
||||
if (filtered.isNotEmpty()) key to filtered else null
|
||||
}
|
||||
}
|
||||
|
||||
fun searchByNameList(
|
||||
list: List<ResultDataFiles>,
|
||||
keyword: String
|
||||
@ -112,7 +105,6 @@ object Common {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 格式化文件大小显示
|
||||
*/
|
||||
@ -261,19 +253,7 @@ object Common {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 去掉缩略图的集合
|
||||
*/
|
||||
suspend fun filterThumbnailsAsync(
|
||||
originalList: MutableList<Pair<String, List<ResultDataFiles>>>
|
||||
): List<Pair<String, List<ResultDataFiles>>> = withContext(Dispatchers.Default) {
|
||||
originalList.asSequence()
|
||||
.map { (key, files) ->
|
||||
key to files.asSequence().filter { !it.isThumbnail }.toList()
|
||||
}
|
||||
.filter { it.second.isNotEmpty() }
|
||||
.toList()
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun removeSelectedFromList(
|
||||
@ -294,12 +274,12 @@ object Common {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun getMediaDuration(filePath: String): Long {
|
||||
val retriever = MediaMetadataRetriever()
|
||||
return try {
|
||||
retriever.setDataSource(filePath)
|
||||
val durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
||||
val durationStr =
|
||||
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
||||
durationStr?.toLongOrNull() ?: 0L // 单位:毫秒
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -323,6 +303,7 @@ object Common {
|
||||
String.format("%02d:%02d", minutes, seconds)
|
||||
}
|
||||
}
|
||||
|
||||
fun getFileMIME(file: File): String {
|
||||
val ext = file.extension.lowercase()
|
||||
val mimeTypeFromExtension = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
||||
@ -340,6 +321,7 @@ object Common {
|
||||
mime == "application/zip" ||
|
||||
mime == "application/x-rar-compressed" ||
|
||||
mime == "application/x-7z-compressed" -> "archive"
|
||||
|
||||
else -> "other"
|
||||
}
|
||||
}
|
||||
@ -348,15 +330,17 @@ object Common {
|
||||
"xapk" to "application/zip",
|
||||
// 可以继续添加其他自定义扩展名
|
||||
)
|
||||
|
||||
fun getMimeTypeParts(file: File): String {
|
||||
val extension = file.extension.lowercase()
|
||||
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)?:customMimeMap[extension]
|
||||
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||
?: customMimeMap[extension]
|
||||
showLog("-----------ext=$extension mimeType=${mimeType}")
|
||||
return if (mimeType != null && mimeType.contains("/")) {
|
||||
val parts = mimeType.split("/")
|
||||
val mainType = parts[0]
|
||||
val subType = parts.getOrNull(1)
|
||||
"$mainType/$subType"
|
||||
"$mainType/$subType"
|
||||
} else {
|
||||
"unknown"
|
||||
}
|
||||
@ -380,7 +364,8 @@ object Common {
|
||||
fun getFormatDate(time: Long): String {
|
||||
return dateFormat.format(Date(time))
|
||||
}
|
||||
fun getItemMonthDay(time: Long): String{
|
||||
|
||||
fun getItemMonthDay(time: Long): String {
|
||||
return itemDateFormat.format(time)
|
||||
}
|
||||
|
||||
@ -400,4 +385,117 @@ object Common {
|
||||
fun showLog(msg: String) {
|
||||
Log.d("============", msg)
|
||||
}
|
||||
|
||||
|
||||
fun shareSingleFile(context: Context, file: File, fileType: FileType) {
|
||||
val uri = FileProvider.getUriForFile(
|
||||
context,
|
||||
"${context.packageName}.fileprovider", // 与 Manifest 保持一致
|
||||
file
|
||||
)
|
||||
|
||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||
type = getMediaFileStr(fileType)
|
||||
putExtra(Intent.EXTRA_STREAM, uri)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
context.startActivity(Intent.createChooser(intent, "分享文件"))
|
||||
}
|
||||
|
||||
fun shareMultipleFiles(context: Context, files: List<File>, fileType: FileType) {
|
||||
val uris = files.map {
|
||||
FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", it)
|
||||
}
|
||||
|
||||
val intent = Intent(Intent.ACTION_SEND_MULTIPLE).apply {
|
||||
type = getMediaFileStr(fileType)
|
||||
putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(uris))
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
|
||||
context.startActivity(Intent.createChooser(intent, "分享多个文件"))
|
||||
}
|
||||
|
||||
fun getResolution(type: FileType, file: File): String {
|
||||
return when (type) {
|
||||
FileType.PHOTO -> {
|
||||
getImageSize(file).run {
|
||||
"$first*$second"
|
||||
}
|
||||
}
|
||||
|
||||
FileType.VIDEO -> getVideoResolution(file.path).run {
|
||||
"$first*$second"
|
||||
}
|
||||
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMediaFileStr(fileType: FileType): String {
|
||||
return when (fileType) {
|
||||
FileType.PHOTO -> "image/*"
|
||||
FileType.VIDEO -> "video/*"
|
||||
FileType.AUDIO -> "audio/*"
|
||||
FileType.DOCUMENT -> "application/*"
|
||||
}
|
||||
}
|
||||
|
||||
private fun getImageSize(file: File): Pair<Int, Int> {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inJustDecodeBounds = true
|
||||
BitmapFactory.decodeFile(file.absolutePath, options)
|
||||
val width = options.outWidth
|
||||
val height = options.outHeight
|
||||
return Pair(width, height)
|
||||
}
|
||||
|
||||
fun shareApp(context: Context) {
|
||||
val appPackageName = context.packageName
|
||||
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(
|
||||
Intent.EXTRA_TEXT,
|
||||
"I recommend a useful app:\nhttps://play.google.com/store/apps/details?id=$appPackageName"
|
||||
)
|
||||
}
|
||||
context.startActivity(
|
||||
Intent.createChooser(shareIntent, "分享应用")
|
||||
)
|
||||
}
|
||||
|
||||
fun getScanType(scanType: ScanType) {
|
||||
when (scanType) {
|
||||
ScanType.ALL_PHOTO -> {}
|
||||
ScanType.DELETED_PHOTO -> {}
|
||||
ScanType.ALL_VIDEO -> {}
|
||||
ScanType.DELETED_VIDEO -> {}
|
||||
ScanType.ALL_AUDIO -> {}
|
||||
ScanType.DELETED_AUDIO -> {}
|
||||
ScanType.ALL_DOCUMENT -> {}
|
||||
ScanType.DELETED_DOCUMENT -> {}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
fun switchFileType(fileType: FileType,onPhoto:()-> Unit,onVideo:()-> Unit,onAudio:()-> Unit,onDocument:()-> Unit){
|
||||
when (fileType) {
|
||||
FileType.PHOTO -> {onPhoto()}
|
||||
FileType.VIDEO -> {onVideo()}
|
||||
FileType.AUDIO -> {onAudio()}
|
||||
FileType.DOCUMENT -> {onDocument()}
|
||||
}
|
||||
}
|
||||
|
||||
fun getScanType1(scanType: ScanType) {
|
||||
when (scanType) {
|
||||
ScanType.ALL_PHOTO, ScanType.DELETED_PHOTO -> {}
|
||||
ScanType.ALL_VIDEO, ScanType.DELETED_VIDEO -> {}
|
||||
ScanType.ALL_AUDIO, ScanType.DELETED_AUDIO -> {}
|
||||
ScanType.ALL_DOCUMENT, ScanType.DELETED_DOCUMENT -> {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -8,6 +8,8 @@ import android.os.Parcelable
|
||||
import android.util.TypedValue
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.duration
|
||||
import com.ux.video.file.filerecovery.db.isThumbnail
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Date
|
||||
@ -24,6 +26,8 @@ object ExtendFunctions {
|
||||
}
|
||||
|
||||
inline fun <reified T : Parcelable> Intent.getParcelableArrayListExtraCompat(key: String): ArrayList<T>? {
|
||||
extras?.classLoader = T::class.java.classLoader
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
getParcelableArrayListExtra(key, T::class.java)
|
||||
} else {
|
||||
@ -134,7 +138,7 @@ object ExtendFunctions {
|
||||
maxSize: Long
|
||||
): List<ResultDataFiles> {
|
||||
if (minSize == -1L) return this
|
||||
return this.filter { it.duration in minSize..maxSize }
|
||||
return this.filter { it.duration() in minSize..maxSize }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,7 +164,7 @@ object ExtendFunctions {
|
||||
): List<Pair<String, List<ResultDataFiles>>> {
|
||||
if (minSize == -1L) return this
|
||||
return this.mapNotNull { (date, files) ->
|
||||
val filtered = files.filter { it.duration in minSize..maxSize }
|
||||
val filtered = files.filter { it.duration() in minSize..maxSize }
|
||||
if (filtered.isNotEmpty()) date to filtered else null
|
||||
}
|
||||
}
|
||||
@ -185,7 +189,7 @@ object ExtendFunctions {
|
||||
withContext(Dispatchers.Default) {
|
||||
this@filterThumbnailsAsync.asSequence()
|
||||
.mapNotNull { (key, files) ->
|
||||
val filtered = files.asSequence().filter { !it.isThumbnail }.toList()
|
||||
val filtered = files.asSequence().filter { !it.isThumbnail() }.toList()
|
||||
if (filtered.isNotEmpty()) key to filtered else null
|
||||
}
|
||||
.toList()
|
||||
@ -198,7 +202,7 @@ object ExtendFunctions {
|
||||
suspend fun List<ResultDataFiles>.filterRemoveThumbnailsAsync(): List<ResultDataFiles> =
|
||||
withContext(Dispatchers.Default) {
|
||||
this@filterRemoveThumbnailsAsync.asSequence()
|
||||
.filter { !it.isThumbnail } // 去掉 isThumbnail = true 的项
|
||||
.filter { !it.isThumbnail() } // 去掉 isThumbnail = true 的项
|
||||
.toList()
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
package com.ux.video.file.filerecovery.utils
|
||||
|
||||
enum class FileType(val value: Int,val tabIndex: Int) {
|
||||
PHOTO(8,0),
|
||||
VIDEO(9,1),
|
||||
AUDIO(10,2),
|
||||
DOCUMENT(11,3);
|
||||
|
||||
companion object {
|
||||
fun from(value: Int): FileType? =
|
||||
FileType.entries.find { it.value == value }
|
||||
}
|
||||
}
|
||||
@ -1,23 +1,17 @@
|
||||
package com.ux.video.file.filerecovery.utils
|
||||
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.media.MediaMetadataRetriever
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.provider.OpenableColumns
|
||||
import android.text.format.Formatter
|
||||
import android.util.Log
|
||||
import com.ux.video.file.filerecovery.db.ResultData
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
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 kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
@ -56,7 +50,7 @@ object ScanManager {
|
||||
context: Context,
|
||||
root: File, maxDepth: Int = 5,
|
||||
maxFiles: Int = 5000,
|
||||
type: Int
|
||||
fileType: FileType
|
||||
): Flow<ScanState> = flow {
|
||||
|
||||
val result = mutableMapOf<String, MutableList<File>>()
|
||||
@ -71,24 +65,7 @@ object ScanManager {
|
||||
if (file.isDirectory) {
|
||||
scanDocuments(file, depth + 1)
|
||||
} else {
|
||||
var fileCheckBoolean: Boolean = false
|
||||
when (type) {
|
||||
VALUE_SCAN_TYPE_photo -> {
|
||||
fileCheckBoolean = isFormatFile(file, IMAGE_FILE) && isValidImage(file)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video -> {
|
||||
fileCheckBoolean = isFormatFile(file, VIDEO_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio -> {
|
||||
fileCheckBoolean = isFormatFile(file, AUDIO_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_documents -> {
|
||||
fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE)
|
||||
}
|
||||
}
|
||||
val fileCheckBoolean: Boolean = checkFileFormat(file,fileType)
|
||||
if (fileCheckBoolean) {
|
||||
val dirName = file.parentFile?.name ?: "Unknown"
|
||||
|
||||
@ -114,8 +91,7 @@ object ScanManager {
|
||||
file.length()
|
||||
),
|
||||
lastModified = file.lastModified(),
|
||||
resolution = getResolution(type, file),
|
||||
fileType = getFileType(type)
|
||||
fileType = fileType
|
||||
)
|
||||
}
|
||||
ResultData(dir, ArrayList(resultDataFilesList))
|
||||
@ -159,9 +135,9 @@ object ScanManager {
|
||||
fun scanHiddenPhotoAsync(
|
||||
context: Context,
|
||||
root: File, maxDepth: Int = 5,
|
||||
maxFiles: Int = 5000, type: Int
|
||||
maxFiles: Int = 5000, fileType: FileType
|
||||
): Flow<ScanState> = flow {
|
||||
|
||||
// scanRecycler(context)
|
||||
val result = mutableMapOf<String, MutableList<File>>()
|
||||
var fileCount = 0
|
||||
|
||||
@ -169,46 +145,52 @@ object ScanManager {
|
||||
suspend fun scanDir(dir: File, depth: Int, insideHidden: Boolean = false) {
|
||||
if (!dir.exists() || !dir.isDirectory) return
|
||||
if (depth > maxDepth || fileCount >= maxFiles) return
|
||||
val skipDirs = setOf(
|
||||
"Android",
|
||||
"obb",
|
||||
"data",
|
||||
".thumbnails",
|
||||
".cache"
|
||||
)
|
||||
|
||||
if (skipDirs.contains(dir.name)) return
|
||||
showLog("HiddenScan", "${dir.name} 111111")
|
||||
|
||||
dir.listFiles()?.forEach { file ->
|
||||
if (file.isDirectory) {
|
||||
val isHidden = file.name.startsWith(".")
|
||||
scanDir(file, depth + 1, insideHidden = insideHidden || isHidden)
|
||||
} else {
|
||||
val fileCheckBoolean: Boolean = checkFileFormat(file,fileType)
|
||||
if (insideHidden) {
|
||||
var fileCheckBoolean: Boolean = false
|
||||
when (type) {
|
||||
VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
fileCheckBoolean =
|
||||
isFormatFile(file, IMAGE_FILE) && isValidImage(file)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_video -> {
|
||||
fileCheckBoolean = isFormatFile(file, VIDEO_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_audio -> {
|
||||
fileCheckBoolean = isFormatFile(file, AUDIO_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_deleted_documents -> {
|
||||
fileCheckBoolean = file.isFile && isFormatFile(file, DOCUMENT_FILE)
|
||||
}
|
||||
}
|
||||
if (fileCheckBoolean) {
|
||||
val dirName = file.parentFile?.name ?: "Unknown"
|
||||
ScanManager.showLog("HiddenScan", "${dirName} 22222")
|
||||
ScanManager.showLog("HiddenScan", "${dirName} 22222 ${file.name}")
|
||||
val list = result.getOrPut(dirName) { mutableListOf() }
|
||||
list.add(file)
|
||||
fileCount++
|
||||
emit(ScanState.Progress(fileCount, file.absolutePath))
|
||||
}
|
||||
} else {
|
||||
if (file.name.startsWith(".") && fileCheckBoolean) {
|
||||
val dirName = file.parentFile?.name ?: "Unknown"
|
||||
ScanManager.showLog("HiddenScan", "${dirName} 33333 ${file.name}")
|
||||
val list = result.getOrPut(dirName) { mutableListOf() }
|
||||
list.add(file)
|
||||
fileCount++
|
||||
emit(ScanState.Progress(fileCount, file.absolutePath))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
scanDir(root, depth = 0)
|
||||
ScanManager.showLog("HiddenScan", " 3333")
|
||||
ScanManager.showLog("HiddenScan", " 44444444")
|
||||
val map = result.map { (dir, files) ->
|
||||
val resultDataFilesList = files.map { file ->
|
||||
ResultDataFiles(
|
||||
@ -220,8 +202,7 @@ object ScanManager {
|
||||
file.length()
|
||||
),
|
||||
lastModified = file.lastModified(),
|
||||
resolution = getResolution(type, file),
|
||||
fileType = getFileType(type)
|
||||
fileType = fileType
|
||||
)
|
||||
|
||||
}
|
||||
@ -231,18 +212,64 @@ object ScanManager {
|
||||
}
|
||||
|
||||
|
||||
private fun getFileType(scanType: Int): Int {
|
||||
return when (scanType) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> 0
|
||||
private fun checkFileFormat(file: File, fileType: FileType): Boolean {
|
||||
return when (fileType) {
|
||||
FileType.PHOTO -> {
|
||||
isFormatFile(file, IMAGE_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> 1
|
||||
FileType.VIDEO -> {
|
||||
isFormatFile(file, VIDEO_FILE)
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> 2
|
||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> 3
|
||||
else -> 3
|
||||
FileType.AUDIO -> {
|
||||
isFormatFile(file, AUDIO_FILE)
|
||||
}
|
||||
|
||||
FileType.DOCUMENT -> {
|
||||
file.isFile && isFormatFile(file, DOCUMENT_FILE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanRecycler(context: Context) {
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.Media._ID,
|
||||
MediaStore.Images.Media.DISPLAY_NAME
|
||||
)
|
||||
|
||||
val selection = "${MediaStore.Images.Media.IS_TRASHED} = ?"
|
||||
val selectionArgs = arrayOf("1")
|
||||
|
||||
val cursor = context.contentResolver.query(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
projection,
|
||||
selection,
|
||||
selectionArgs,
|
||||
null
|
||||
)
|
||||
Log.d("Trash", "cursor=$cursor ")
|
||||
cursor?.use {
|
||||
Log.d("Trash", "11111111")
|
||||
while (it.moveToNext()) {
|
||||
Log.d("Trash", "2222222222")
|
||||
val id = it.getLong(0)
|
||||
val name = it.getString(1)
|
||||
|
||||
val uri = ContentUris.withAppendedId(
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
id
|
||||
)
|
||||
|
||||
// 这是“可恢复”的文件
|
||||
Log.d("Trash", "name=$name uri=$uri")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun getFileSizeByMediaStore(context: Context, file: File): Long {
|
||||
val uri = Uri.fromFile(file)
|
||||
context.contentResolver.query(uri, arrayOf(OpenableColumns.SIZE), null, null, null)
|
||||
@ -255,23 +282,24 @@ object ScanManager {
|
||||
return file.length() // fallback
|
||||
}
|
||||
|
||||
private fun getResolution(type: Int, file: File): String {
|
||||
return when (type) {
|
||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
getImageSize(file).run {
|
||||
"$first*$second"
|
||||
}
|
||||
}
|
||||
|
||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> getVideoResolution(file.path).run {
|
||||
"$first*$second"
|
||||
}
|
||||
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
// private fun getResolution(type: Int, file: File): String {
|
||||
// return when (type) {
|
||||
// VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||
// getImageSize(file).run {
|
||||
// "$first*$second"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> getVideoResolution(file.path).run {
|
||||
// "$first*$second"
|
||||
// }
|
||||
//
|
||||
// else -> ""
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun isFormatFile(file: File, types: List<String>): Boolean {
|
||||
if (!file.exists() || file.length() <= 0) return false
|
||||
val ext = file.extension.lowercase()
|
||||
return types.contains(ext)
|
||||
}
|
||||
@ -284,6 +312,7 @@ object ScanManager {
|
||||
Log.d(tag, msg)
|
||||
}
|
||||
|
||||
|
||||
fun isValidImage(file: File): Boolean {
|
||||
if (!file.exists() || file.length() <= 0) return false
|
||||
return try {
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package com.ux.video.file.filerecovery.utils
|
||||
|
||||
enum class ScanType(val value: Int) {
|
||||
|
||||
ALL_PHOTO(0),
|
||||
DELETED_PHOTO(1),
|
||||
|
||||
ALL_VIDEO(2),
|
||||
DELETED_VIDEO(3),
|
||||
|
||||
ALL_AUDIO(4),
|
||||
DELETED_AUDIO(5),
|
||||
|
||||
ALL_DOCUMENT(6),
|
||||
DELETED_DOCUMENT(7);
|
||||
|
||||
|
||||
val mediaType: FileType
|
||||
get() = when (this) {
|
||||
ALL_PHOTO, DELETED_PHOTO -> FileType.PHOTO
|
||||
ALL_VIDEO, DELETED_VIDEO -> FileType.VIDEO
|
||||
ALL_AUDIO, DELETED_AUDIO -> FileType.AUDIO
|
||||
ALL_DOCUMENT, DELETED_DOCUMENT -> FileType.DOCUMENT
|
||||
}
|
||||
|
||||
val isDeletedScan: Boolean
|
||||
get() = when (this) {
|
||||
DELETED_PHOTO,
|
||||
DELETED_VIDEO,
|
||||
DELETED_AUDIO,
|
||||
DELETED_DOCUMENT -> true
|
||||
else -> false
|
||||
}
|
||||
companion object {
|
||||
fun from(value: Int): ScanType? =
|
||||
ScanType.entries.find { it.value == value }
|
||||
}
|
||||
}
|
||||
@ -107,4 +107,9 @@ class PlayMediaManager(var context: Context, var mediaFile: File, var playView:
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun stopPlayAudio(){
|
||||
player.stop()
|
||||
|
||||
}
|
||||
}
|
||||
@ -15,8 +15,10 @@ import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivityVideoPlayBinding
|
||||
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||
import com.ux.video.file.filerecovery.db.targetFile
|
||||
import com.ux.video.file.filerecovery.success.RecoverySuccessActivity
|
||||
import com.ux.video.file.filerecovery.utils.Common
|
||||
import com.ux.video.file.filerecovery.utils.FileType
|
||||
|
||||
class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
||||
|
||||
@ -48,10 +50,10 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
||||
binding.run {
|
||||
myData?.let { resultPhotosFiles->
|
||||
imageBack.setOnClickListener { finish() }
|
||||
resultPhotosFiles.targetFile?.let {
|
||||
resultPhotosFiles.targetFile().let {
|
||||
PlayMediaManager(context = this@VideoPlayActivity, mediaFile = it, playView = playerView,
|
||||
seekBar = seekBar, playBtn = playImage, onUpdateProgress = { current,total->
|
||||
textTimeCurrent.text = current
|
||||
textTimeCurrent.text = current
|
||||
textTimeTotal.text = total
|
||||
} )
|
||||
}
|
||||
@ -141,7 +143,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
||||
myData?.let {
|
||||
player = ExoPlayer.Builder(this).build()
|
||||
binding.playerView.player = player
|
||||
val mediaItem = MediaItem.fromUri(Uri.fromFile(it.targetFile))
|
||||
val mediaItem = MediaItem.fromUri(Uri.fromFile(it.targetFile()))
|
||||
player.addListener(object : Player.Listener {
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
super.onPlaybackStateChanged(playbackState)
|
||||
@ -177,6 +179,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
||||
startActivity(Intent(this@VideoPlayActivity, RecoverySuccessActivity::class.java).apply {
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_COUNT, number)
|
||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
||||
putExtra(Common.KEY_FILE_TYPE, FileType.VIDEO.value)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.ux.video.file.filerecovery.welcome
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||
import com.ux.video.file.filerecovery.databinding.ActivitySplashBinding
|
||||
import com.ux.video.file.filerecovery.main.MainActivity
|
||||
import com.ux.video.file.filerecovery.recovery.RecoveryActivity
|
||||
|
||||
class SplashActivity : BaseActivity<ActivitySplashBinding>() {
|
||||
|
||||
|
||||
override fun inflateBinding(inflater: LayoutInflater): ActivitySplashBinding =
|
||||
ActivitySplashBinding.inflate(inflater)
|
||||
|
||||
override fun initView() {
|
||||
super.initView()
|
||||
binding.textEnter.setOnClickListener {
|
||||
startActivity(Intent(this@SplashActivity, MainActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
}
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
7
app/src/main/res/drawable/bg_000000_10.xml
Normal file
7
app/src/main/res/drawable/bg_000000_10.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="10dp"/>
|
||||
<solid android:color="@color/dialog_delete_success_color"/>
|
||||
|
||||
</shape>
|
||||
10
app/src/main/res/drawable/bg_welcome_enter.xml
Normal file
10
app/src/main/res/drawable/bg_welcome_enter.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="50dp" />
|
||||
<gradient
|
||||
android:angle="180"
|
||||
android:endColor="@color/welcome_enter_start_color"
|
||||
android:startColor="@color/welcome_enter_end_color" />
|
||||
|
||||
</shape>
|
||||
BIN
app/src/main/res/drawable/icon_privacy_policy.png
Normal file
BIN
app/src/main/res/drawable/icon_privacy_policy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/drawable/icon_share_app.png
Normal file
BIN
app/src/main/res/drawable/icon_share_app.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/drawable/photo_place_holder.png
Normal file
BIN
app/src/main/res/drawable/photo_place_holder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
app/src/main/res/drawable/welcome_bg.png
Normal file
BIN
app/src/main/res/drawable/welcome_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 846 KiB |
@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
tools:context=".sort.PhotoInfoActivity">
|
||||
tools:context=".detail.DetailsActivity">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -27,6 +27,7 @@
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:id="@+id/im_setting"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
||||
@ -186,7 +187,7 @@
|
||||
android:id="@+id/layout_recovery"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/main_type_bg"
|
||||
android:gravity="center_vertical"
|
||||
@ -219,6 +220,7 @@
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginStart="11dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/main_type_bg"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
@ -243,66 +245,8 @@
|
||||
app:fontType="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_wchat">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_permission"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="管理所有文件的权限申请" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan_all_photo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="扫描所有图片" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan_all_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="扫描所有视频" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan_all_audio"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="扫描所有音频" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_scan_all_file"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="扫描所有文件" />
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_permission"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/allow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="50dp"
|
||||
android:text="Allow" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
tools:context=".sort.PhotoSortingActivity">
|
||||
tools:context=".sort.SortingActivity">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_top"
|
||||
|
||||
@ -1,17 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".documents.DocumentsScanResultActivity">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
tools:context=".settings.PrivacyPolicyActivity">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
101
app/src/main/res/layout/activity_set_up.xml
Normal file
101
app/src/main/res/layout/activity_set_up.xml
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
tools:context=".settings.SetupActivity">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="13dp"
|
||||
android:paddingVertical="14dp"
|
||||
android:src="@drawable/black_return" />
|
||||
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="@string/settings"
|
||||
android:textColor="@color/main_title"
|
||||
android:textSize="16sp"
|
||||
app:fontType="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_share_app"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="0dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_share_app"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/icon_share_app" />
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/im_share_app"
|
||||
android:text="@string/share_app"
|
||||
android:textColor="@color/main_title"
|
||||
android:textSize="14sp"
|
||||
app:fontType="bold" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@color/dividing_line_color" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_privacy_policy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="0dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_privacy_policy"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/icon_privacy_policy" />
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/im_privacy_policy"
|
||||
android:text="@string/privacy_policy"
|
||||
android:textColor="@color/main_title"
|
||||
android:textSize="14sp"
|
||||
app:fontType="bold" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@color/dividing_line_color" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
52
app/src/main/res/layout/activity_splash.xml
Normal file
52
app/src/main/res/layout/activity_splash.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/welcome_bg"
|
||||
tools:context=".welcome.SplashActivity">
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginTop="87dp"
|
||||
android:text="@string/welcome_name"
|
||||
android:textColor="@color/main_title"
|
||||
android:textSize="48sp"
|
||||
app:fontType="alimama"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/welcome_sub_text"
|
||||
android:textColor="@color/main_sub_title"
|
||||
android:textSize="16sp"
|
||||
app:fontType="bold"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_name" />
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:id="@+id/text_enter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginHorizontal="60dp"
|
||||
android:layout_marginBottom="80dp"
|
||||
android:background="@drawable/bg_welcome_enter"
|
||||
android:gravity="center"
|
||||
android:text="@string/enter"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp"
|
||||
app:fontType="alimama"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
26
app/src/main/res/layout/dialog_delete_success.xml
Normal file
26
app/src/main/res/layout/dialog_delete_success.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/bg_000000_10"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/icon_checkmark_16dp"/>
|
||||
|
||||
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/white"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/deleted_success"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
@ -11,7 +11,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/selector_recovery_file_tab_layout_title"
|
||||
android:textSize="15sp"
|
||||
android:textSize="13sp"
|
||||
android:gravity="center"
|
||||
app:fontType="bold" />
|
||||
|
||||
|
||||
BIN
app/src/main/res/mipmap-xxxhdpi/recovery.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/recovery.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
13
app/src/main/res/values-v31/themes.xml
Normal file
13
app/src/main/res/values-v31/themes.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- <style name="Theme.FileRecovery" parent="Theme.SplashScreen">-->
|
||||
<!-- <item name="windowSplashScreenBackground">@color/black</item>-->
|
||||
<!-- <item name="windowSplashScreenAnimatedIcon">@mipmap/recovery</item>-->
|
||||
<!-- <item name="postSplashScreenTheme">@style/Theme.FileRecovery</item>-->
|
||||
<!-- </style>-->
|
||||
<style name="Base.Theme.FileRecovery" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
<item name="android:windowBackground">@color/white</item>
|
||||
</style>
|
||||
</resources>
|
||||
@ -26,5 +26,8 @@
|
||||
<color name="view_div_color">#D9D9D9</color>
|
||||
<color name="bg_seekbar_video_play">#99F2F2F7</color>
|
||||
|
||||
<color name="dialog_delete_success_color">#98000000</color>
|
||||
<color name="welcome_enter_start_color">#70ABFF</color>
|
||||
<color name="welcome_enter_end_color">#326EFF</color>
|
||||
|
||||
</resources>
|
||||
@ -1,10 +1,13 @@
|
||||
<resources>
|
||||
<string name="app_name">File Recovery</string>
|
||||
<string name="app_name">File Recovery Tool</string>
|
||||
<string name="scan_all_file">Scan all files</string>
|
||||
<string name="scan_deleted_files">Scan deleted files</string>
|
||||
<string name="select_all">Select all</string>
|
||||
<string name="select">Select</string>
|
||||
<string name="deselect_all">Deselect all</string>
|
||||
<string name="enter">ENTER</string>
|
||||
<string name="welcome_name">File\nRecovery</string>
|
||||
<string name="welcome_sub_text">Important files shouldn\'t just disappear.</string>
|
||||
|
||||
|
||||
<string name="size_kb">%.2f KB</string>
|
||||
@ -29,7 +32,7 @@
|
||||
<string name="audio_title">Audio recovery</string>
|
||||
<string name="document_title">Document recovery</string>
|
||||
<string name="permission_request">Permission is required to access all files</string>
|
||||
<string name="permission_request_content">File Recovery -All Recovery requires full access to your device storage to search for lost or deleted files.</string>
|
||||
<string name="permission_request_content">File Recovery Tool -All Recovery requires full access to your device storage to search for lost or deleted files.</string>
|
||||
<string name="permission_request_promote">We will never share, upload, or send your data without your permission.</string>
|
||||
|
||||
<string name="cancel">Cancel</string>
|
||||
@ -88,7 +91,7 @@ wait..</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="recovered_files">Recovered files</string>
|
||||
<string name="text_counts">(%d)</string>
|
||||
<string name="warning">Please do not uninstall the File Recovery -
|
||||
<string name="warning">Please do not uninstall the File Recovery Tool -
|
||||
All Recovery to avoid file loss.</string>
|
||||
<string name="no_files">No files have been recovered yet~</string>
|
||||
<string name="scan_photos">Scan photos</string>
|
||||
@ -96,7 +99,11 @@ All Recovery to avoid file loss.</string>
|
||||
<string name="scan_audios">Scan audios</string>
|
||||
<string name="scan_documents">Scan documents</string>
|
||||
<string name="share_placeholder">Share (%d)</string>
|
||||
|
||||
<string name="settings">Settings</string>
|
||||
<string name="share_app">Share App</string>
|
||||
<string name="share">Share</string>
|
||||
<string name="privacy_policy">Privacy Policy</string>
|
||||
<string name="privacy_policy_url">https://file-filerecovery.bitbucket.io//privacy.html</string>
|
||||
|
||||
|
||||
<string-array name="filter_date">
|
||||
|
||||
12
app/src/main/res/xml/file_paths.xml
Normal file
12
app/src/main/res/xml/file_paths.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 指向公共根目录 /storage/emulated/0 -->
|
||||
<external-path
|
||||
name="scanned_root"
|
||||
path="." />
|
||||
|
||||
<!-- 推荐:用于分享时的临时缓存目录 -->
|
||||
<external-cache-path
|
||||
name="share_cache"
|
||||
path="share/" />
|
||||
</paths>
|
||||
@ -2,10 +2,12 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
id("com.google.gms.google-services") version "4.4.2" apply false
|
||||
id ("com.google.firebase.crashlytics") version "3.0.2" apply false
|
||||
}
|
||||
buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath("io.objectbox:objectbox-gradle-plugin:4.0.3")
|
||||
classpath("io.objectbox:objectbox-gradle-plugin:5.0.1")
|
||||
}
|
||||
}
|
||||
@ -20,4 +20,7 @@ kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
systemProp.http.proxyHost=127.0.0.1
|
||||
systemProp.http.proxyPort=2080
|
||||
6
keystore.properties
Normal file
6
keystore.properties
Normal file
@ -0,0 +1,6 @@
|
||||
app_name=File Recovery
|
||||
package_name=com.ux.video.file.filerecovery
|
||||
keystoreFile=app/FileRecovery
|
||||
key_alias=FileRecoverykey0
|
||||
key_store_password=FileRecovery
|
||||
key_password=FileRecovery
|
||||
Loading…
Reference in New Issue
Block a user