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 {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
id ("kotlin-kapt")
|
id ("kotlin-kapt")
|
||||||
id ("kotlin-parcelize")
|
id ("kotlin-parcelize")
|
||||||
id("io.objectbox")
|
id("io.objectbox")
|
||||||
|
id("com.google.gms.google-services")
|
||||||
|
id("com.google.firebase.crashlytics")
|
||||||
}
|
}
|
||||||
|
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||||
android {
|
android {
|
||||||
namespace = "com.ux.video.file.filerecovery"
|
namespace = "com.ux.video.file.filerecovery"
|
||||||
compileSdk = 36
|
compileSdk = 36
|
||||||
@ -16,13 +21,13 @@ android {
|
|||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0"
|
versionName = "1.0"
|
||||||
|
project.setProperty("archivesBaseName", "File Recovery Tool" + versionName + "(${versionCode})_$timestamp")
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
@ -56,9 +61,17 @@ dependencies {
|
|||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
implementation (libs.glide)
|
implementation (libs.glide)
|
||||||
kapt (libs.compiler)
|
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 ("com.google.android.material:material:1.13.0")
|
||||||
implementation(project(":pickerview"))
|
implementation(project(":pickerview"))
|
||||||
implementation ("androidx.media3:media3-exoplayer:1.8.0")
|
implementation ("androidx.media3:media3-exoplayer:1.8.0")
|
||||||
implementation ("androidx.media3:media3-ui: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",
|
"id": "7:8305655849151310709",
|
||||||
"name": "lastModified",
|
"name": "lastModified",
|
||||||
"type": 6
|
"type": 6
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "8:5134665607056785092",
|
|
||||||
"name": "resolution",
|
|
||||||
"type": 9
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"relations": []
|
"relations": []
|
||||||
@ -71,7 +66,8 @@
|
|||||||
3831579248666795267,
|
3831579248666795267,
|
||||||
4445203567182319472,
|
4445203567182319472,
|
||||||
6858261029979256233,
|
6858261029979256233,
|
||||||
2835789057594891780
|
2835789057594891780,
|
||||||
|
5134665607056785092
|
||||||
],
|
],
|
||||||
"retiredRelationUids": [],
|
"retiredRelationUids": [],
|
||||||
"version": 1
|
"version": 1
|
||||||
|
|||||||
59
app/proguard-rules.pro
vendored
59
app/proguard-rules.pro
vendored
@ -19,3 +19,62 @@
|
|||||||
# If you keep the line number information, uncomment this to
|
# If you keep the line number information, uncomment this to
|
||||||
# hide the original source file name.
|
# 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:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/recovery"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/recovery"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.FileRecovery"
|
android:theme="@style/Theme.FileRecovery"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".recovery.RecoveryActivity"
|
android:name=".settings.PrivacyPolicyActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".video.VideoPlayActivity"
|
android:name=".settings.SetupActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".sort.PhotoInfoActivity"
|
android:name=".welcome.SplashActivity"
|
||||||
android:exported="false" />
|
android:exported="true"
|
||||||
<activity
|
android:screenOrientation="portrait"
|
||||||
android:name=".sort.PhotoSortingActivity"
|
tools:ignore="SplashScreen">
|
||||||
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">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -13,6 +13,9 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding
|
import com.ux.video.file.filerecovery.databinding.DialogRecoveringBinding
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除/恢复中父类弹窗
|
||||||
|
*/
|
||||||
abstract class BaseIngDialogFragment() : DialogFragment() {
|
abstract class BaseIngDialogFragment() : DialogFragment() {
|
||||||
var total: Int = 0
|
var total: Int = 0
|
||||||
var completeListener: ((number: Int) -> Unit)? = null
|
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
|
package com.ux.video.file.filerecovery.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.BoxStore
|
import io.objectbox.BoxStore
|
||||||
import io.objectbox.config.DebugFlags
|
import io.objectbox.config.DebugFlags
|
||||||
import io.objectbox.reactive.DataSubscription
|
import io.objectbox.reactive.DataSubscription
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.jvm.java
|
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 {
|
// fun queryIsLike(id: Long): Boolean {
|
||||||
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||||
@ -113,10 +132,10 @@ object ObjectBoxManager {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun queryRecoveryFileAsync(type: Int): List<ResultDataFiles> =
|
suspend fun queryRecoveryFileAsync(type: FileType): List<ResultDataFiles> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val dataBox = getDataBox()
|
val dataBox = getDataBox()
|
||||||
dataBox.query(ResultDataFiles_.fileType.equal(type))
|
dataBox.query(ResultDataFiles_.fileType.equal(type.value))
|
||||||
.build()
|
.build()
|
||||||
.find()
|
.find()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import java.io.File
|
|||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
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.Entity
|
||||||
import io.objectbox.annotation.Id
|
import io.objectbox.annotation.Id
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
@ -13,35 +15,40 @@ import kotlinx.parcelize.Parcelize
|
|||||||
data class ResultDataFiles(
|
data class ResultDataFiles(
|
||||||
@Id
|
@Id
|
||||||
var id: Long = 0,
|
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 name: String,
|
||||||
val path: String,
|
val path: String,
|
||||||
val size: Long, // 字节
|
val size: Long, // 字节
|
||||||
val sizeString: String,
|
val sizeString: String,
|
||||||
val lastModified: Long, // 时间戳
|
val lastModified: Long, // 时间戳
|
||||||
var resolution: String // 尺寸
|
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
val targetFile: File?
|
// val targetFile: File
|
||||||
get() = path?.let { File(it) }
|
// get() = path.let { File(it) }
|
||||||
|
|
||||||
|
//尺寸
|
||||||
|
// val resolution: String
|
||||||
|
// get() = Common.getResolution(fileType, targetFile)
|
||||||
|
|
||||||
//是否为缩略图文件(宽高任一小于 256)
|
//是否为缩略图文件(宽高任一小于 256)
|
||||||
val isThumbnail: Boolean
|
// val isThumbnail: Boolean
|
||||||
get() {
|
// get() {
|
||||||
val parts = resolution.lowercase().split("*").mapNotNull {
|
// val parts = resolution.lowercase().split("*").mapNotNull {
|
||||||
it.trim().toIntOrNull()
|
// it.trim().toIntOrNull()
|
||||||
}
|
// }
|
||||||
if (parts.size == 2) {
|
// if (parts.size == 2) {
|
||||||
val (width, height) = parts
|
// val (width, height) = parts
|
||||||
return width < 256 || height < 256
|
// return width < 256 || height < 256
|
||||||
}
|
// }
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
//音视频时长
|
//音视频时长
|
||||||
val duration: Long
|
// val duration: Long
|
||||||
get() {
|
// get() {
|
||||||
return Common.getMediaDuration(path.toString()) }
|
// 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.os.Environment
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import androidx.activity.OnBackPressedCallback
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityMainBinding
|
import com.ux.video.file.filerecovery.databinding.ActivityMainBinding
|
||||||
import com.ux.video.file.filerecovery.recovery.RecoveryActivity
|
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
|
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||||
|
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
private var dialogCustomerDateStart:DatePickerDialogFragment? = null
|
private var pendingAction: NavigateAction? = null
|
||||||
private var dialogPermission: PermissionDialogFragment? = null
|
private var dialogPermission: PermissionDialogFragment? = null
|
||||||
|
|
||||||
//是否正确引导用户打开所有文件管理权限
|
//是否正确引导用户打开所有文件管理权限
|
||||||
private var isRequestPermission = false
|
private var isRequestPermission = false
|
||||||
private var currentGoType = ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
|
||||||
private val requestPermissionLauncher =
|
private val requestPermissionLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||||
var isAllOK = true
|
var isAllOK = true
|
||||||
@ -54,47 +54,49 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
super.initView()
|
super.initView()
|
||||||
onBackPressedDispatcher.addCallback(
|
// onBackPressedDispatcher.addCallback(
|
||||||
this,
|
// this,
|
||||||
object : OnBackPressedCallback(true) {
|
// object : OnBackPressedCallback(true) {
|
||||||
override fun handleOnBackPressed() {
|
// override fun handleOnBackPressed() {
|
||||||
ScanManager.showLog("权限", "====0000000")
|
// ScanManager.showLog("权限", "====0000000")
|
||||||
if (binding.layoutPermission.isVisible) {
|
// if (binding.layoutPermission.isVisible) {
|
||||||
ScanManager.showLog("权限", "====111111")
|
// ScanManager.showLog("权限", "====111111")
|
||||||
binding.layoutPermission.visibility = View.GONE
|
//// binding.layoutPermission.visibility = View.GONE
|
||||||
} else {
|
// } else {
|
||||||
ScanManager.showLog("权限", "====222222222222")
|
// ScanManager.showLog("权限", "====222222222222")
|
||||||
finish()
|
// finish()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
initTitleColor()
|
initTitleColor()
|
||||||
binding.run {
|
binding.run {
|
||||||
allow.setOnClickListener {
|
imSetting.setOnClickListener {
|
||||||
|
startActivity(Intent(this@MainActivity, SetupActivity::class.java))
|
||||||
|
|
||||||
}
|
}
|
||||||
layoutPhoto.setOnClickListener {
|
layoutPhoto.setOnClickListener {
|
||||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
pendingAction = NavigateAction.Scan(FileType.PHOTO)
|
||||||
intentCheck()
|
intentCheck()
|
||||||
}
|
}
|
||||||
layoutVideo.setOnClickListener {
|
layoutVideo.setOnClickListener {
|
||||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_VIDEO
|
pendingAction = NavigateAction.Scan(FileType.VIDEO)
|
||||||
intentCheck()
|
intentCheck()
|
||||||
}
|
}
|
||||||
layoutAudio.setOnClickListener {
|
layoutAudio.setOnClickListener {
|
||||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_AUDIO
|
pendingAction = NavigateAction.Scan(FileType.AUDIO)
|
||||||
intentCheck()
|
intentCheck()
|
||||||
}
|
}
|
||||||
layoutDocument.setOnClickListener {
|
layoutDocument.setOnClickListener {
|
||||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
pendingAction = NavigateAction.Scan(FileType.DOCUMENT)
|
||||||
intentCheck()
|
intentCheck()
|
||||||
}
|
}
|
||||||
layoutRecovery.setOnClickListener {
|
layoutRecovery.setOnClickListener {
|
||||||
startActivity(Intent(this@MainActivity,RecoveryActivity::class.java))
|
pendingAction = NavigateAction.Recovered
|
||||||
|
intentCheck()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.tvTitle.setOnClickListener {
|
binding.tvTitle.setOnClickListener {
|
||||||
@ -102,53 +104,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
showDatePicker()
|
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() {
|
private fun initTitleColor() {
|
||||||
@ -158,7 +113,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
val width = paint.measureText(text.toString())
|
val width = paint.measureText(text.toString())
|
||||||
val shader = LinearGradient(
|
val shader = LinearGradient(
|
||||||
0f, 0f, width, textSize,
|
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,
|
null,
|
||||||
Shader.TileMode.CLAMP
|
Shader.TileMode.CLAMP
|
||||||
)
|
)
|
||||||
@ -177,7 +135,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
isRequestPermission = false
|
isRequestPermission = false
|
||||||
ScanManager.showLog("--", "-------onResume")
|
ScanManager.showLog("--", "-------onResume")
|
||||||
startScan()
|
startScan()
|
||||||
binding.layoutPermission.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +168,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private fun requestPermission() {
|
private fun requestPermission() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
dialogPermission = dialogPermission?: PermissionDialogFragment{
|
dialogPermission = dialogPermission ?: PermissionDialogFragment {
|
||||||
try {
|
try {
|
||||||
val intent =
|
val intent =
|
||||||
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
|
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
|
||||||
@ -224,7 +181,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
isRequestPermission = true
|
isRequestPermission = true
|
||||||
}
|
}
|
||||||
dialogPermission?.show(supportFragmentManager,"")
|
dialogPermission?.show(supportFragmentManager, "")
|
||||||
} else {
|
} else {
|
||||||
requestPermissionLauncher.launch(
|
requestPermissionLauncher.launch(
|
||||||
arrayOf(
|
arrayOf(
|
||||||
@ -236,14 +193,31 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startScan() {
|
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() {
|
override fun onDestroy() {
|
||||||
super.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.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityScanSelectTypeBinding
|
import com.ux.video.file.filerecovery.databinding.ActivityScanSelectTypeBinding
|
||||||
import com.ux.video.file.filerecovery.result.ScanningActivity
|
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
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
|
import com.ux.video.file.filerecovery.utils.ScanType
|
||||||
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 kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
|
||||||
@ -23,14 +17,6 @@ import kotlin.properties.Delegates
|
|||||||
*/
|
*/
|
||||||
class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
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 allType by Delegates.notNull<Int>()
|
||||||
private var deletedType by Delegates.notNull<Int>()
|
private var deletedType by Delegates.notNull<Int>()
|
||||||
override fun inflateBinding(inflater: LayoutInflater): ActivityScanSelectTypeBinding =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityScanSelectTypeBinding =
|
||||||
@ -39,8 +25,10 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
|||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
super.initView()
|
super.initView()
|
||||||
val type = intent.getIntExtra(KEY_FILE_TYPE, VALUE_PHOTO)
|
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||||
setSelectType(type)
|
val fileType = FileType.from(intExtra)
|
||||||
|
fileType?.let { setSelectType(it) }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,40 +38,40 @@ class ScanSelectTypeActivity : BaseActivity<ActivityScanSelectTypeBinding>() {
|
|||||||
binding.scanAllFile.setOnClickListener {
|
binding.scanAllFile.setOnClickListener {
|
||||||
|
|
||||||
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
|
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
|
||||||
putExtra(KEY_SCAN_TYPE, allType)
|
putExtra(Common.KEY_SCAN_TYPE, allType)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
binding.scanDeletedFile.setOnClickListener {
|
binding.scanDeletedFile.setOnClickListener {
|
||||||
startActivity(Intent(this@ScanSelectTypeActivity, ScanningActivity::class.java).apply {
|
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) {
|
when (fileType) {
|
||||||
VALUE_PHOTO -> {
|
FileType.PHOTO -> {
|
||||||
allType = VALUE_SCAN_TYPE_photo
|
allType = ScanType.ALL_PHOTO.value
|
||||||
deletedType = VALUE_SCAN_TYPE_deleted_photo
|
deletedType = ScanType.DELETED_PHOTO.value
|
||||||
binding.title.text = getString(R.string.photo_title)
|
binding.title.text = getString(R.string.photo_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_VIDEO -> {
|
FileType.VIDEO -> {
|
||||||
allType = VALUE_SCAN_TYPE_video
|
allType = ScanType.ALL_VIDEO.value
|
||||||
deletedType = VALUE_SCAN_TYPE_deleted_video
|
deletedType = ScanType.DELETED_VIDEO.value
|
||||||
binding.title.text = getString(R.string.video_title)
|
binding.title.text = getString(R.string.video_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_AUDIO -> {
|
FileType.AUDIO -> {
|
||||||
allType = VALUE_SCAN_TYPE_audio
|
allType = ScanType.ALL_AUDIO.value
|
||||||
deletedType = VALUE_SCAN_TYPE_deleted_audio
|
deletedType = ScanType.DELETED_AUDIO.value
|
||||||
binding.title.text = getString(R.string.audio_title)
|
binding.title.text = getString(R.string.audio_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_DOCUMENT -> {
|
FileType.DOCUMENT -> {
|
||||||
allType = VALUE_SCAN_TYPE_documents
|
allType = ScanType.ALL_DOCUMENT.value
|
||||||
deletedType = VALUE_SCAN_TYPE_deleted_documents
|
deletedType = ScanType.DELETED_DOCUMENT.value
|
||||||
binding.title.text = getString(R.string.document_title)
|
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.databinding.ActivityRecoveryBinding
|
||||||
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
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.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.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
import com.ux.video.file.filerecovery.utils.CustomTextView
|
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
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
||||||
val sharedViewModel: RecoveryPhotoViewModel by viewModels()
|
val sharedViewModel: RecoveryPhotoViewModel by viewModels()
|
||||||
|
private lateinit var fileType: FileType
|
||||||
|
|
||||||
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding =
|
||||||
ActivityRecoveryBinding.inflate(inflater)
|
ActivityRecoveryBinding.inflate(inflater)
|
||||||
|
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
super.initView()
|
super.initView()
|
||||||
|
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||||
|
fileType = FileType.from(intExtra)!!
|
||||||
binding.run {
|
binding.run {
|
||||||
val fragments = listOf(
|
val fragments = listOf(
|
||||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_PHOTO),
|
RecoveredFragment.newInstance(FileType.PHOTO.value),
|
||||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_VIDEO),
|
RecoveredFragment.newInstance(FileType.VIDEO.value),
|
||||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_AUDIO),
|
RecoveredFragment.newInstance(FileType.AUDIO.value),
|
||||||
RecoveryPhotoFragment.newInstance(Common.FILE_TYPE_DOCUMENTS)
|
RecoveredFragment.newInstance(FileType.DOCUMENT.value)
|
||||||
)
|
)
|
||||||
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity, fragments)
|
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity, fragments)
|
||||||
TabLayoutMediator(tabLayout, viewPage2) { tab, position ->
|
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 {
|
binding.imageBack.setOnClickListener {
|
||||||
finish()
|
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 {
|
lifecycleScope.launch {
|
||||||
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_PHOTO)
|
FileType.entries.forEach{ fileType->
|
||||||
sharedViewModel.setPhotosRecoveredFiles(recoveryFilePhoto)
|
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(fileType)
|
||||||
val recoveryFileVideo = ObjectBoxManager.queryRecoveryFileAsync(Common.FILE_TYPE_VIDEO)
|
sharedViewModel.setRecoveredFiles(fileType, recoveryFilePhoto)
|
||||||
sharedViewModel.setVideosRecoveredFiles(recoveryFileVideo)
|
setTabCount(fileType, recoveryFilePhoto.size)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,38 +5,55 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* RecoveryActivity RecoveredFragment 共用
|
||||||
|
*/
|
||||||
class RecoveryPhotoViewModel : ViewModel() {
|
class RecoveryPhotoViewModel : ViewModel() {
|
||||||
private val _photoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
|
||||||
|
//用于及时更新tab 显示恢复文件的数量
|
||||||
|
private val _photoFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||||
val photoFiles: LiveData<List<ResultDataFiles>> = _photoFiles
|
val photoFiles: LiveData<List<ResultDataFiles>> = _photoFiles
|
||||||
|
|
||||||
private val _videoFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
private val _videoFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||||
val videoFiles: LiveData< List<ResultDataFiles>> = _videoFiles
|
val videoFiles: LiveData<List<ResultDataFiles>> = _videoFiles
|
||||||
|
|
||||||
private val _audioFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
private val _audioFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||||
val audioFiles: LiveData< List<ResultDataFiles>> = _audioFiles
|
val audioFiles: LiveData<List<ResultDataFiles>> = _audioFiles
|
||||||
|
|
||||||
private val _documentsFiles = MutableLiveData< List<ResultDataFiles>>(emptyList())
|
private val _documentsFiles = MutableLiveData<List<ResultDataFiles>>(emptyList())
|
||||||
val documentsFiles: LiveData< List<ResultDataFiles>> = _documentsFiles
|
val documentsFiles: LiveData<List<ResultDataFiles>> = _documentsFiles
|
||||||
|
|
||||||
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
|
||||||
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
|
|
||||||
|
|
||||||
fun setPhotosRecoveredFiles(photos:List<ResultDataFiles>){
|
private val _selectedPhotoLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
_photoFiles.value = photos
|
val selectedPhoto: LiveData<Set<ResultDataFiles>> = _selectedPhotoLiveData
|
||||||
}
|
|
||||||
fun setVideosRecoveredFiles(videos:List<ResultDataFiles>){
|
private val _selectedVideoLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
_videoFiles.value = videos
|
val selectedVideo: LiveData<Set<ResultDataFiles>> = _selectedVideoLiveData
|
||||||
}
|
|
||||||
fun setAudiosRecoveredFiles(audios:List<ResultDataFiles>){
|
private val _selectedAudioLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
_audioFiles.value = audios
|
val selectedAudio: LiveData<Set<ResultDataFiles>> = _selectedAudioLiveData
|
||||||
}
|
|
||||||
fun setDocumentsRecoveredFiles(documents:List<ResultDataFiles>){
|
private val _selectedDocumentsLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
_documentsFiles.value = documents
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSelection(isAdd: Boolean, resultDataFiles: ResultDataFiles) {
|
}
|
||||||
val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
|
|
||||||
|
|
||||||
|
fun toggleSelection(fileType: FileType, isAdd: Boolean, resultDataFiles: ResultDataFiles) {
|
||||||
|
getSelectedList(fileType).let { selectList ->
|
||||||
|
val current = selectList.value?.toMutableSet() ?: mutableSetOf()
|
||||||
resultDataFiles.let {
|
resultDataFiles.let {
|
||||||
if (isAdd) {
|
if (isAdd) {
|
||||||
current.add(it)
|
current.add(it)
|
||||||
@ -44,11 +61,46 @@ class RecoveryPhotoViewModel : ViewModel() {
|
|||||||
current.remove(it)
|
current.remove(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_selectedLiveData.value = current.toSet()
|
selectList.value = current.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkIsSelect(resultDataFiles: ResultDataFiles): Boolean {
|
}
|
||||||
val current = _selectedLiveData.value
|
|
||||||
return current?.contains(resultDataFiles) == true
|
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.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityScanResultDisplayBinding
|
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.ResultData
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.sort.SortingActivity
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
|
import com.ux.video.file.filerecovery.utils.ScanType
|
||||||
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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扫描结果汇总展示
|
* 扫描结果汇总展示
|
||||||
*/
|
*/
|
||||||
class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>() {
|
class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>() {
|
||||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
private lateinit var scanType: ScanType
|
||||||
private var exitDialog: ExitDialogFragment? = null
|
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 =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityScanResultDisplayBinding =
|
||||||
ActivityScanResultDisplayBinding.inflate(inflater)
|
ActivityScanResultDisplayBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
super.initView()
|
super.initView()
|
||||||
list = intent.getParcelableArrayListExtraCompat(KEY_SCAN_RESULT)
|
val intExtra = intent.getIntExtra(Common.KEY_SCAN_TYPE, ScanType.ALL_PHOTO.value)
|
||||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
scanType = ScanType.from(intExtra)!!
|
||||||
setSelectTypeTitle(scanType)
|
setSelectTypeTitle(scanType.mediaType)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
@ -59,12 +48,12 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
|||||||
})
|
})
|
||||||
|
|
||||||
binding.run {
|
binding.run {
|
||||||
val myAdapter = when (scanType) {
|
val myAdapter = when (scanType.mediaType) {
|
||||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.AUDIO, FileType.DOCUMENT -> {
|
||||||
bottomLayout.setBackgroundResource(R.drawable.bg_rectangle_white_top_20)
|
bottomLayout.setBackgroundResource(R.drawable.bg_rectangle_white_top_20)
|
||||||
ScanResultDocumentsAdapter(
|
ScanResultDocumentsAudioAdapter(
|
||||||
this@ScanResultDisplayActivity,
|
this@ScanResultDisplayActivity,
|
||||||
scanType
|
scanType.mediaType
|
||||||
) { folderLists ->
|
) { folderLists ->
|
||||||
goSort(folderLists)
|
goSort(folderLists)
|
||||||
}
|
}
|
||||||
@ -72,60 +61,56 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
bottomLayout.setBackgroundResource(0)
|
bottomLayout.setBackgroundResource(0)
|
||||||
ScanResultPhotoAdapter(
|
ScanResultPhotoVideoAdapter(
|
||||||
this@ScanResultDisplayActivity,
|
this@ScanResultDisplayActivity,
|
||||||
scanType
|
scanType.mediaType
|
||||||
) { folderLists ->
|
) { folderLists ->
|
||||||
goSort(folderLists)
|
goSort(folderLists)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
viewModel.scanData.observe(this@ScanResultDisplayActivity){ data->
|
||||||
}.apply {
|
list = data
|
||||||
list?.let {
|
list.let { data ->
|
||||||
textDirCount.text = it.size.toString()
|
textDirCount.text = data.size.toString()
|
||||||
val sumOf = it.sumOf { it.allFiles.size }
|
val sumOf = data.sumOf { it.allFiles.size }
|
||||||
textAllCounts.text = sumOf.toString()
|
textAllCounts.text = sumOf.toString()
|
||||||
setData(it)
|
myAdapter.setData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recyclerResult.run {
|
recyclerResult.run {
|
||||||
adapter = myAdapter
|
adapter = myAdapter
|
||||||
layoutManager = LinearLayoutManager(this@ScanResultDisplayActivity)
|
layoutManager = LinearLayoutManager(this@ScanResultDisplayActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun dealExit() {
|
private fun dealExit() {
|
||||||
exitDialog = exitDialog ?: ExitDialogFragment() {
|
exitDialog = exitDialog ?: ExitDialogFragment {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
exitDialog?.show(supportFragmentManager, "")
|
exitDialog?.show(supportFragmentManager, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setSelectTypeTitle(fileType: Int) {
|
private fun setSelectTypeTitle(fileType: FileType) {
|
||||||
binding.run {
|
binding.run {
|
||||||
when (fileType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
FileType.PHOTO -> {
|
||||||
title.text = getString(R.string.photo_title)
|
title.text = getString(R.string.photo_title)
|
||||||
textFileType.text = getString(R.string.text_photos)
|
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)
|
title.text = getString(R.string.video_title)
|
||||||
textFileType.text = getString(R.string.text_videos)
|
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)
|
title.text = getString(R.string.audio_title)
|
||||||
textFileType.text = getString(R.string.text_audios)
|
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)
|
title.text = getString(R.string.document_title)
|
||||||
textFileType.text = getString(R.string.text_documents)
|
textFileType.text = getString(R.string.text_documents)
|
||||||
}
|
}
|
||||||
@ -137,16 +122,13 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
|||||||
|
|
||||||
|
|
||||||
private fun goSort(list: ArrayList<ResultDataFiles>) {
|
private fun goSort(list: ArrayList<ResultDataFiles>) {
|
||||||
|
viewModel.updateSortData(list)
|
||||||
startActivity(
|
startActivity(
|
||||||
Intent(
|
Intent(
|
||||||
this@ScanResultDisplayActivity,
|
this@ScanResultDisplayActivity,
|
||||||
PhotoSortingActivity::class.java
|
SortingActivity::class.java
|
||||||
).apply {
|
).apply {
|
||||||
putExtra(KEY_SCAN_TYPE, scanType)
|
putExtra(Common.KEY_FILE_TYPE, scanType.mediaType.value)
|
||||||
putParcelableArrayListExtra(
|
|
||||||
PhotoSortingActivity.KEY_PHOTO_FOLDER_FILE,
|
|
||||||
list
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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.ResultData
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件或者音频的扫描结果汇总适配器
|
* 文件或者音频的扫描结果汇总适配器
|
||||||
*/
|
*/
|
||||||
class ScanResultDocumentsAdapter(
|
class ScanResultDocumentsAudioAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var type: Int,
|
var fileType: FileType,
|
||||||
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<ResultData, ScanResultDocumentsAdapterBinding>(mContext) {
|
BaseAdapter<ResultData, ScanResultDocumentsAdapterBinding>(mContext) {
|
||||||
@ -38,13 +39,15 @@ class ScanResultDocumentsAdapter(
|
|||||||
relativeLayout.setOnClickListener { onClickItem(allFiles) }
|
relativeLayout.setOnClickListener { onClickItem(allFiles) }
|
||||||
textDirName.text = dirName
|
textDirName.text = dirName
|
||||||
textFileCounts.text = allFiles.size.toString()
|
textFileCounts.text = allFiles.size.toString()
|
||||||
when(type){
|
when(fileType){
|
||||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio->{
|
FileType.AUDIO ->{
|
||||||
icon.setImageResource(R.drawable.icon_folder_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)
|
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.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
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.CenterCrop
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
import com.bumptech.glide.request.RequestOptions
|
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.base.BaseAdapter
|
||||||
import com.ux.video.file.filerecovery.databinding.ScanResultAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.ScanResultAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.db.ResultData
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.ExtendFunctions.dpToPx
|
||||||
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ScanResultPhotoAdapter(
|
/**
|
||||||
|
* 图片或者视频的扫描结果汇总适配器
|
||||||
|
*/
|
||||||
|
class ScanResultPhotoVideoAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var type: Int,
|
var fileType: FileType,
|
||||||
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<ResultData, ScanResultAdapterBinding>(mContext) {
|
BaseAdapter<ResultData, ScanResultAdapterBinding>(mContext) {
|
||||||
@ -45,7 +53,7 @@ class ScanResultPhotoAdapter(
|
|||||||
val takeFiles = allFiles.take(3)
|
val takeFiles = allFiles.take(3)
|
||||||
imageViews.forEachIndexed { index, imageView ->
|
imageViews.forEachIndexed { index, imageView ->
|
||||||
if (index < takeFiles.size) {
|
if (index < takeFiles.size) {
|
||||||
takeFiles[index].targetFile?.let {
|
takeFiles[index].targetFile().let {
|
||||||
loadImageView(mContext, it, imageView)
|
loadImageView(mContext, it, imageView)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -61,12 +69,17 @@ class ScanResultPhotoAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadImageView(context: Context, file: File, imageView: ImageView) {
|
private fun loadImageView(context: Context, file: File, imageView: ImageView) {
|
||||||
|
ScanManager.showLog(
|
||||||
|
"加载图片",
|
||||||
|
"-----loadImageView--path = ${file.path}"
|
||||||
|
)
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(file)
|
.load(file)
|
||||||
.apply(
|
.apply(
|
||||||
RequestOptions()
|
RequestOptions()
|
||||||
.transform(CenterCrop(), RoundedCorners(8.dpToPx(context)))
|
.transform(CenterCrop(), RoundedCorners(8.dpToPx(context)))
|
||||||
)
|
)
|
||||||
|
.error(R.drawable.photo_place_holder)
|
||||||
.into(imageView)
|
.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.content.Intent
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityScanningBinding
|
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.utils.Common
|
||||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
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.ScanManager
|
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.ScanState
|
||||||
|
import com.ux.video.file.filerecovery.utils.ScanType
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
|
||||||
|
|
||||||
class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
||||||
|
|
||||||
|
private val viewModel: ScanningActivityViewModel by viewModels()
|
||||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
private lateinit var scanType: ScanType
|
||||||
override fun inflateBinding(inflater: LayoutInflater): ActivityScanningBinding =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityScanningBinding =
|
||||||
ActivityScanningBinding.inflate(inflater)
|
ActivityScanningBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.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)
|
setSelectType(scanType)
|
||||||
when (scanType) {
|
if (scanType.isDeletedScan) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_documents -> scanAll()
|
scanDeleted()
|
||||||
VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_deleted_video, VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_deleted_documents -> scanDeleted()
|
} else {
|
||||||
|
scanAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.imageViewBack.setOnClickListener { finish() }
|
binding.imageViewBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setSelectType(fileType: Int) {
|
private fun setSelectType(scanType: ScanType) {
|
||||||
binding.run {
|
binding.run {
|
||||||
|
when (scanType.mediaType) {
|
||||||
when (fileType) {
|
FileType.PHOTO->{
|
||||||
VALUE_SCAN_TYPE_photo -> {
|
|
||||||
title.text = getString(R.string.photo_title)
|
title.text = getString(R.string.photo_title)
|
||||||
tvScanDescribe.text = getString(R.string.describe_photos)
|
|
||||||
scanProgress.setCenterImage(R.drawable.im_photo_center_image)
|
scanProgress.setCenterImage(R.drawable.im_photo_center_image)
|
||||||
}
|
if(scanType.isDeletedScan){
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_deleted_photo -> {
|
|
||||||
title.text = getString(R.string.photo_title)
|
|
||||||
tvScanDescribe.text = getString(R.string.describe_delete_photos)
|
tvScanDescribe.text = getString(R.string.describe_delete_photos)
|
||||||
scanProgress.setCenterImage(R.drawable.im_photo_center_image)
|
}else{
|
||||||
|
tvScanDescribe.text = getString(R.string.describe_photos)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VALUE_SCAN_TYPE_video -> {
|
FileType.VIDEO->{
|
||||||
title.text = getString(R.string.video_title)
|
title.text = getString(R.string.video_title)
|
||||||
tvScanDescribe.text = getString(R.string.describe_videos)
|
|
||||||
scanProgress.setCenterImage(R.drawable.im_video_center_image)
|
scanProgress.setCenterImage(R.drawable.im_video_center_image)
|
||||||
}
|
if(scanType.isDeletedScan){
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_deleted_video -> {
|
|
||||||
title.text = getString(R.string.video_title)
|
|
||||||
tvScanDescribe.text = getString(R.string.describe_delete_videos)
|
tvScanDescribe.text = getString(R.string.describe_delete_videos)
|
||||||
scanProgress.setCenterImage(R.drawable.im_video_center_image)
|
}else{
|
||||||
|
tvScanDescribe.text = getString(R.string.describe_videos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_audio -> {
|
FileType.AUDIO->{
|
||||||
title.text = getString(R.string.audio_title)
|
title.text = getString(R.string.audio_title)
|
||||||
tvScanDescribe.text = getString(R.string.describe_audios)
|
|
||||||
scanProgress.setCenterImage(R.drawable.im_audio_center_image)
|
scanProgress.setCenterImage(R.drawable.im_audio_center_image)
|
||||||
}
|
if(scanType.isDeletedScan){
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_deleted_audio -> {
|
|
||||||
title.text = getString(R.string.audio_title)
|
|
||||||
tvScanDescribe.text = getString(R.string.describe_delete_audios)
|
tvScanDescribe.text = getString(R.string.describe_delete_audios)
|
||||||
scanProgress.setCenterImage(R.drawable.im_audio_center_image)
|
}else{
|
||||||
|
tvScanDescribe.text = getString(R.string.describe_audios)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VALUE_SCAN_TYPE_documents -> {
|
FileType.DOCUMENT->{
|
||||||
title.text = getString(R.string.document_title)
|
title.text = getString(R.string.document_title)
|
||||||
tvScanDescribe.text = getString(R.string.describe_documents)
|
|
||||||
scanProgress.setCenterImage(R.drawable.im_documents_center_image)
|
scanProgress.setCenterImage(R.drawable.im_documents_center_image)
|
||||||
}
|
if(scanType.isDeletedScan){
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_deleted_documents -> {
|
|
||||||
title.text = getString(R.string.document_title)
|
|
||||||
tvScanDescribe.text = getString(R.string.describe_delete_documents)
|
tvScanDescribe.text = getString(R.string.describe_delete_documents)
|
||||||
scanProgress.setCenterImage(R.drawable.im_documents_center_image)
|
}else{
|
||||||
|
tvScanDescribe.text = getString(R.string.describe_documents)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +93,7 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
|||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
val root = Environment.getExternalStorageDirectory()
|
val root = Environment.getExternalStorageDirectory()
|
||||||
ScanManager.scanAllDocuments(this@ScanningActivity, root, type = scanType)
|
ScanManager.scanAllDocuments(this@ScanningActivity, root, fileType = scanType.mediaType)
|
||||||
.flowOn(Dispatchers.IO).collect {
|
.flowOn(Dispatchers.IO).collect {
|
||||||
when (it) {
|
when (it) {
|
||||||
is ScanState.Progress -> {
|
is ScanState.Progress -> {
|
||||||
@ -126,8 +106,6 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +113,7 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
|||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
val root = Environment.getExternalStorageDirectory()
|
val root = Environment.getExternalStorageDirectory()
|
||||||
ScanManager.scanHiddenPhotoAsync(this@ScanningActivity, root, type = scanType)
|
ScanManager.scanHiddenPhotoAsync(this@ScanningActivity, root, fileType = scanType.mediaType)
|
||||||
.flowOn(Dispatchers.IO).collect {
|
.flowOn(Dispatchers.IO).collect {
|
||||||
when (it) {
|
when (it) {
|
||||||
is ScanState.Progress -> {
|
is ScanState.Progress -> {
|
||||||
@ -182,18 +160,19 @@ class ScanningActivity : BaseActivity<ActivityScanningBinding>() {
|
|||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
tvScanDescribe.text.let {
|
tvScanDescribe.text.let {
|
||||||
tvEmptyTypeFile.text = "0 $it"
|
tvEmptyTypeFile.text = "0 $it"
|
||||||
tvSorry.text = getString(R.string.not_found,it)
|
tvSorry.text = getString(R.string.not_found, it)
|
||||||
}
|
}
|
||||||
relativeScanFinishedEmpty.isVisible = true
|
relativeScanFinishedEmpty.isVisible = true
|
||||||
linearCounts.isVisible = false
|
linearCounts.isVisible = false
|
||||||
}else{
|
} else {
|
||||||
finish()
|
finish()
|
||||||
startActivity(Intent(this@ScanningActivity, ScanResultDisplayActivity::class.java).apply {
|
viewModel.updateData(it.result)
|
||||||
putParcelableArrayListExtra(
|
startActivity(
|
||||||
ScanResultDisplayActivity.KEY_SCAN_RESULT,
|
Intent(
|
||||||
it.result
|
this@ScanningActivity,
|
||||||
)
|
ScanResultDisplayActivity::class.java
|
||||||
putExtra(KEY_SCAN_TYPE, scanType)
|
).apply {
|
||||||
|
putExtra(Common.KEY_SCAN_TYPE, scanType.value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ScanManager.showLog("HiddenScan", "完成: ${it.result.size}")
|
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() {
|
class SortDialogFragment(val onClickSort: (type: Int) -> Unit) : DialogFragment() {
|
||||||
|
|
||||||
private lateinit var binding: DialogSortBinding
|
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>
|
private lateinit var LayoutList: List<CommonLayoutSortItemBinding>
|
||||||
override fun onStart() {
|
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.base.BaseAdapter
|
||||||
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.PhotoDisplayDateAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.db.isThumbnail
|
||||||
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
|
|
||||||
|
|
||||||
class PhotoDisplayDateAdapter(
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序页面显示
|
||||||
|
*/
|
||||||
|
class SortDisplayAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var scanType: Int,
|
var fileType: FileType,
|
||||||
var mColumns: Int,
|
var mColumns: Int,
|
||||||
var viewModel: ScanRepository,
|
var viewModel: SortingViewModel,
|
||||||
var onSelectedUpdate: (resultDataFiles: ResultDataFiles, isAdd: Boolean) -> Unit,
|
var onSelectedUpdate: (resultDataFiles: ResultDataFiles, isAdd: Boolean) -> Unit,
|
||||||
var clickItem: (item: ResultDataFiles) -> Unit
|
var clickItem: (item: ResultDataFiles) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<Pair<String, List<ResultDataFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
|
BaseAdapter<Pair<String, List<ResultDataFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
|
||||||
|
|
||||||
|
|
||||||
private var allSelected: Boolean? = null
|
private var allSelected: Boolean? = null
|
||||||
|
|
||||||
override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateAdapterBinding =
|
override fun getViewBinding(parent: ViewGroup): PhotoDisplayDateAdapterBinding =
|
||||||
@ -41,7 +41,7 @@ class PhotoDisplayDateAdapter(
|
|||||||
*/
|
*/
|
||||||
fun getTotalChildCount(hideThumbnails: Boolean): Int {
|
fun getTotalChildCount(hideThumbnails: Boolean): Int {
|
||||||
if (hideThumbnails) {
|
if (hideThumbnails) {
|
||||||
return data.sumOf { it.second.filter { !it.isThumbnail }.size }
|
return data.sumOf { it.second.filter { !it.isThumbnail() }.size }
|
||||||
} else {
|
} else {
|
||||||
return data.sumOf { it.second.size }
|
return data.sumOf { it.second.size }
|
||||||
}
|
}
|
||||||
@ -80,9 +80,9 @@ class PhotoDisplayDateAdapter(
|
|||||||
holder.vb.run {
|
holder.vb.run {
|
||||||
item.run {
|
item.run {
|
||||||
val (date, files) = item
|
val (date, files) = item
|
||||||
val childAdapter = PhotoDisplayDateChildAdapter(
|
val childAdapter = SortDisplayChildAdapter(
|
||||||
mContext,
|
mContext,
|
||||||
scanType,
|
fileType,
|
||||||
mColumns,
|
mColumns,
|
||||||
viewModel,
|
viewModel,
|
||||||
{ resultPhotosFiles, addOrRemove, isDateAllSelected ->
|
{ resultPhotosFiles, addOrRemove, isDateAllSelected ->
|
||||||
@ -108,8 +108,8 @@ class PhotoDisplayDateAdapter(
|
|||||||
textChildCounts.text = "(${files.size})"
|
textChildCounts.text = "(${files.size})"
|
||||||
|
|
||||||
recyclerChild.apply {
|
recyclerChild.apply {
|
||||||
layoutManager = when (scanType) {
|
layoutManager = when (fileType) {
|
||||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.AUDIO, FileType.DOCUMENT -> {
|
||||||
LinearLayoutManager(context)
|
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.OneAudioItemBinding
|
||||||
import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding
|
import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.recovery.ui.recoveryphoto.RecoveryPhotoViewModel
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
import com.ux.video.file.filerecovery.utils.CustomTextView
|
import com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
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.ScanManager
|
||||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
|
||||||
|
|
||||||
class PhotoDisplayDateChildAdapter(
|
|
||||||
|
/**
|
||||||
|
* 排序页面显示 、已经恢复的文件页面显示
|
||||||
|
*/
|
||||||
|
class SortDisplayChildAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var scanType: Int,
|
var fileType: FileType,
|
||||||
var mColumns: Int,
|
var mColumns: Int,
|
||||||
var viewModel: ViewModel? = null,
|
var viewModel: ViewModel? = null,
|
||||||
/**
|
/**
|
||||||
@ -72,12 +78,12 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio -> {
|
FileType.AUDIO -> {
|
||||||
return TYPE_AUDIO
|
return TYPE_AUDIO
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.VALUE_SCAN_TYPE_documents, Common.VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.DOCUMENT -> {
|
||||||
return TYPE_DOCUMENTS
|
return TYPE_DOCUMENTS
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,20 +178,10 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
item.run {
|
item.run {
|
||||||
holder.vb.let {
|
holder.vb.let {
|
||||||
it.textName.text = name
|
it.textName.text = name
|
||||||
it.textDuration.text = Common.formatDuration(duration)
|
it.textDuration.text = Common.formatDuration(duration())
|
||||||
it.textSize.text = sizeString
|
it.textSize.text = sizeString
|
||||||
|
|
||||||
initAudioDocuments(it.imageSelect, this)
|
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 {
|
it.constraintLayout.setOnClickListener {
|
||||||
clickItem(this)
|
clickItem(this)
|
||||||
}
|
}
|
||||||
@ -200,7 +196,7 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
it.textName.text = name
|
it.textName.text = name
|
||||||
it.textDate.text = Common.getItemMonthDay(lastModified)
|
it.textDate.text = Common.getItemMonthDay(lastModified)
|
||||||
it.textSize.text = sizeString
|
it.textSize.text = sizeString
|
||||||
targetFile?.let { file ->
|
targetFile().let { file ->
|
||||||
it.imageIcon.setImageResource(Common.getFileIconRes(file))
|
it.imageIcon.setImageResource(Common.getFileIconRes(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,11 +231,11 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
private fun initAudioDocuments(imageSelect: ImageView, item: ResultDataFiles) {
|
private fun initAudioDocuments(imageSelect: ImageView, item: ResultDataFiles) {
|
||||||
|
|
||||||
viewModel?.let {
|
viewModel?.let {
|
||||||
if (it is ScanRepository) {
|
if (it is SortingViewModel) {
|
||||||
it.checkIsSelect(item)
|
it.checkIsSelect(item)
|
||||||
} else {
|
} else {
|
||||||
it as RecoveryPhotoViewModel
|
it as RecoveryPhotoViewModel
|
||||||
it.checkIsSelect(item)
|
it.checkIsSelect(fileType, item)
|
||||||
}.let { isSelected ->
|
}.let { isSelected ->
|
||||||
imageSelect.isSelected = isSelected == true
|
imageSelect.isSelected = isSelected == true
|
||||||
addOrRemove(item, isSelected == true)
|
addOrRemove(item, isSelected == true)
|
||||||
@ -265,31 +261,21 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
) {
|
) {
|
||||||
item.run {
|
item.run {
|
||||||
initAudioDocuments(imageSelectStatus, this)
|
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
|
textSize.text = sizeString
|
||||||
|
|
||||||
imageType.setImageResource(
|
imageType.setImageResource(
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
Common.VALUE_SCAN_TYPE_photo, Common.VALUE_SCAN_TYPE_deleted_photo -> R.drawable.icon_type_photo
|
FileType.PHOTO -> R.drawable.icon_type_photo
|
||||||
Common.VALUE_SCAN_TYPE_video, Common.VALUE_SCAN_TYPE_deleted_video -> R.drawable.icon_type_video
|
FileType.VIDEO -> R.drawable.icon_type_video
|
||||||
else -> R.drawable.icon_type_photo
|
else -> R.drawable.icon_type_photo
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Glide.with(mContext)
|
Glide.with(mContext)
|
||||||
.load(targetFile)
|
.load(targetFile())
|
||||||
.apply(
|
.apply(
|
||||||
RequestOptions()
|
RequestOptions()
|
||||||
.transform(CenterCrop(), RoundedCorners(8.dpToPx(mContext)))
|
.transform(CenterCrop(), RoundedCorners(8.dpToPx(mContext)))
|
||||||
)
|
)
|
||||||
|
.error(R.drawable.photo_place_holder)
|
||||||
.listener(object : RequestListener<Drawable> {
|
.listener(object : RequestListener<Drawable> {
|
||||||
override fun onLoadFailed(
|
override fun onLoadFailed(
|
||||||
e: GlideException?,
|
e: GlideException?,
|
||||||
@ -299,7 +285,7 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
ScanManager.showLog(
|
ScanManager.showLog(
|
||||||
"加载图片",
|
"加载图片",
|
||||||
"-------path = ${path} file=${targetFile}"
|
"-------path = ${path} e=${e?.message}"
|
||||||
)
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -6,8 +6,8 @@ import android.text.TextWatcher
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
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.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
|
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.success.RecoverySuccessActivity
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
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.Common.setItemSelect
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterByDuration
|
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.filterThumbnailsAsync
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.filterWithinDateRange
|
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.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.kbToBytes
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.mbToBytes
|
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.minutesToMillisecond
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.removeItem
|
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.GridSpacingItemDecoration
|
||||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
import com.ux.video.file.filerecovery.utils.ScanType
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
class SortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
//指定文件夹下的所有文件
|
//指定文件夹下的所有文件
|
||||||
@ -67,14 +60,14 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
val SORT_DESC_DATE = 3
|
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 sortDialogFragment: SortDialogFragment? = null
|
||||||
private var columns = 3
|
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
|
private var dialogCustomerDateStart: DatePickerDialogFragment? = null
|
||||||
@ -118,20 +111,86 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
private lateinit var sizeFilterItemArray: Array<String>
|
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() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
val intExtra = intent.getIntExtra(Common.KEY_FILE_TYPE, FileType.PHOTO.value)
|
||||||
val list: ArrayList<ResultDataFiles>? =
|
|
||||||
intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE)
|
fileType = FileType.from(intExtra)!!
|
||||||
mItemDecoration =
|
mItemDecoration =
|
||||||
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
|
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
|
||||||
updateButtonCounts(0)
|
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 ->
|
viewModel.selectedLiveData.observe(this) { selectedSet ->
|
||||||
allSelectedSetList = selectedSet
|
allSelectedSetList = selectedSet
|
||||||
@ -144,64 +203,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
updateCurrentIsAllSelectStatus()
|
updateCurrentIsAllSelectStatus()
|
||||||
}
|
}
|
||||||
setScanTypeView()
|
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() }
|
imageViewBack.setOnClickListener { finish() }
|
||||||
switchHideThumbnails.setOnCheckedChangeListener { _, isChecked ->
|
switchHideThumbnails.setOnCheckedChangeListener { _, isChecked ->
|
||||||
when (recyclerView.adapter) {
|
when (recyclerView.adapter) {
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
dateAdapter?.run {
|
dateAdapter?.run {
|
||||||
initGetCurrentDateList().let { list ->
|
initGetCurrentDateList().let { list ->
|
||||||
@ -225,7 +227,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
sizeSortAdapter?.run {
|
sizeSortAdapter?.run {
|
||||||
initGetCurrentSizeList().let {
|
initGetCurrentSizeList().let {
|
||||||
@ -336,7 +338,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
tvSelectAll.setOnClickListener {
|
tvSelectAll.setOnClickListener {
|
||||||
it.isSelected = !it.isSelected
|
it.isSelected = !it.isSelected
|
||||||
when (binding.recyclerView.adapter) {
|
when (binding.recyclerView.adapter) {
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
dateAdapter?.setAllSelected(it.isSelected)
|
dateAdapter?.setAllSelected(it.isSelected)
|
||||||
dateAdapter?.getCurrentData()?.let {
|
dateAdapter?.getCurrentData()?.let {
|
||||||
it as List<Pair<String, List<ResultDataFiles>>>
|
it as List<Pair<String, List<ResultDataFiles>>>
|
||||||
@ -346,7 +348,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
sizeSortAdapter?.setAllSelected(it.isSelected)
|
sizeSortAdapter?.setAllSelected(it.isSelected)
|
||||||
sizeSortAdapter?.getCurrentData()?.let {
|
sizeSortAdapter?.getCurrentData()?.let {
|
||||||
it as List<ResultDataFiles>
|
it as List<ResultDataFiles>
|
||||||
@ -367,8 +369,9 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
*/
|
*/
|
||||||
private fun setScanTypeView() {
|
private fun setScanTypeView() {
|
||||||
binding.run {
|
binding.run {
|
||||||
when (scanType) {
|
fileType?.let {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
when (it) {
|
||||||
|
FileType.PHOTO -> {
|
||||||
titleSize.text = getString(R.string.size)
|
titleSize.text = getString(R.string.size)
|
||||||
filterLayoutLinearlayout.isVisible = true
|
filterLayoutLinearlayout.isVisible = true
|
||||||
relativeThumbnails.isVisible = true
|
relativeThumbnails.isVisible = true
|
||||||
@ -376,7 +379,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_size_photo)
|
sizeFilterItemArray = resources.getStringArray(R.array.filter_size_photo)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> {
|
FileType.VIDEO -> {
|
||||||
titleSize.text = getString(R.string.duration)
|
titleSize.text = getString(R.string.duration)
|
||||||
filterLayoutLinearlayout.isVisible = true
|
filterLayoutLinearlayout.isVisible = true
|
||||||
relativeThumbnails.isVisible = false
|
relativeThumbnails.isVisible = false
|
||||||
@ -385,7 +388,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
resources.getStringArray(R.array.filter_duration_video_audio)
|
resources.getStringArray(R.array.filter_duration_video_audio)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
FileType.AUDIO -> {
|
||||||
titleSize.text = getString(R.string.duration)
|
titleSize.text = getString(R.string.duration)
|
||||||
filterLayoutLinearlayout.isVisible = false
|
filterLayoutLinearlayout.isVisible = false
|
||||||
relativeThumbnails.isVisible = false
|
relativeThumbnails.isVisible = false
|
||||||
@ -395,7 +398,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
initSearch()
|
initSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.DOCUMENT -> {
|
||||||
titleSize.text = getString(R.string.size)
|
titleSize.text = getString(R.string.size)
|
||||||
filterLayoutLinearlayout.isVisible = false
|
filterLayoutLinearlayout.isVisible = false
|
||||||
relativeThumbnails.isVisible = false
|
relativeThumbnails.isVisible = false
|
||||||
@ -403,6 +406,9 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
sizeFilterItemArray = resources.getStringArray(R.array.filter_documents_size)
|
sizeFilterItemArray = resources.getStringArray(R.array.filter_documents_size)
|
||||||
initSearch()
|
initSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -413,8 +419,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
binding.tvSelectCounts.text = it.toString()
|
binding.tvSelectCounts.text = it.toString()
|
||||||
updateButtonCounts(it)
|
updateButtonCounts(it)
|
||||||
when (binding.recyclerView.adapter) {
|
when (binding.recyclerView.adapter) {
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
val adapter = binding.recyclerView.adapter as PhotoDisplayDateAdapter
|
val adapter = binding.recyclerView.adapter as SortDisplayAdapter
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
binding.tvSelectAll.isSelected = it == adapter.getTotalChildCount(false)
|
binding.tvSelectAll.isSelected = it == adapter.getTotalChildCount(false)
|
||||||
} else {
|
} else {
|
||||||
@ -423,8 +429,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
val adapter = binding.recyclerView.adapter as PhotoDisplayDateChildAdapter
|
val adapter = binding.recyclerView.adapter as SortDisplayChildAdapter
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
binding.tvSelectAll.isSelected =
|
binding.tvSelectAll.isSelected =
|
||||||
it == adapter.itemCount
|
it == adapter.itemCount
|
||||||
@ -448,7 +454,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
currentDateList = null
|
currentDateList = null
|
||||||
|
|
||||||
binding.tvThumbnailCounts.text =
|
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
|
currentDateList = currentList
|
||||||
currentSizeList = null
|
currentSizeList = null
|
||||||
val totalSelectedCount = currentList.sumOf { pair ->
|
val totalSelectedCount = currentList.sumOf { pair ->
|
||||||
pair.second.filter { it.isThumbnail }.size
|
pair.second.filter { it.isThumbnail() }.size
|
||||||
}
|
}
|
||||||
binding.tvThumbnailCounts.text =
|
binding.tvThumbnailCounts.text =
|
||||||
getString(R.string.hide_thumbnails, totalSelectedCount)
|
getString(R.string.hide_thumbnails, totalSelectedCount)
|
||||||
@ -474,7 +480,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
private fun setDateAdapter() {
|
private fun setDateAdapter() {
|
||||||
binding.recyclerView.run {
|
binding.recyclerView.run {
|
||||||
adapter = dateAdapter?.apply { setColumns(columns) }
|
adapter = dateAdapter?.apply { setColumns(columns) }
|
||||||
layoutManager = LinearLayoutManager(this@PhotoSortingActivity)
|
layoutManager = LinearLayoutManager(this@SortingActivity)
|
||||||
setPadding(0, 0, 0, 70.dpToPx(context))
|
setPadding(0, 0, 0, 70.dpToPx(context))
|
||||||
clipToPadding = false
|
clipToPadding = false
|
||||||
}
|
}
|
||||||
@ -484,8 +490,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
binding.recyclerView.run {
|
binding.recyclerView.run {
|
||||||
val aPx = 16.dpToPx(context)
|
val aPx = 16.dpToPx(context)
|
||||||
val bottom = 70.dpToPx(context)
|
val bottom = 70.dpToPx(context)
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio,VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.AUDIO, FileType.DOCUMENT-> {
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
setPadding(aPx, 0, 0, bottom)
|
setPadding(aPx, 0, 0, bottom)
|
||||||
}
|
}
|
||||||
@ -513,7 +519,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
setItemSelect(it as LinearLayout, true)
|
setItemSelect(it as LinearLayout, true)
|
||||||
resources.getStringArray(R.array.filter_date).let { data ->
|
resources.getStringArray(R.array.filter_date).let { data ->
|
||||||
filterDatePopupWindows = filterDatePopupWindows ?: DateFilterPopupWindows(
|
filterDatePopupWindows = filterDatePopupWindows ?: DateFilterPopupWindows(
|
||||||
this@PhotoSortingActivity,
|
this@SortingActivity,
|
||||||
0,
|
0,
|
||||||
{ clickValue, showDialog ->
|
{ clickValue, showDialog ->
|
||||||
when (clickValue) {
|
when (clickValue) {
|
||||||
@ -576,7 +582,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
setItemSelect(it as LinearLayout, true)
|
setItemSelect(it as LinearLayout, true)
|
||||||
sizeFilterItemArray.let { data ->
|
sizeFilterItemArray.let { data ->
|
||||||
filterSizePopupWindows = filterSizePopupWindows ?: FilterPopupWindows(
|
filterSizePopupWindows = filterSizePopupWindows ?: FilterPopupWindows(
|
||||||
this@PhotoSortingActivity,
|
this@SortingActivity,
|
||||||
data,
|
data,
|
||||||
0,
|
0,
|
||||||
{ clickValue ->
|
{ clickValue ->
|
||||||
@ -598,7 +604,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
setItemSelect(it as LinearLayout, true)
|
setItemSelect(it as LinearLayout, true)
|
||||||
resources.getStringArray(R.array.filter_layout).let { data ->
|
resources.getStringArray(R.array.filter_layout).let { data ->
|
||||||
filterLayoutPopupWindows = filterLayoutPopupWindows ?: FilterPopupWindows(
|
filterLayoutPopupWindows = filterLayoutPopupWindows ?: FilterPopupWindows(
|
||||||
this@PhotoSortingActivity,
|
this@SortingActivity,
|
||||||
data,
|
data,
|
||||||
1,
|
1,
|
||||||
{ clickValue ->
|
{ clickValue ->
|
||||||
@ -608,13 +614,13 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
data[2] -> columns = 4
|
data[2] -> columns = 4
|
||||||
}
|
}
|
||||||
when (binding.recyclerView.adapter) {
|
when (binding.recyclerView.adapter) {
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
dateAdapter?.setColumns(columns)
|
dateAdapter?.setColumns(columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
binding.recyclerView.layoutManager =
|
binding.recyclerView.layoutManager =
|
||||||
GridLayoutManager(this@PhotoSortingActivity, columns)
|
GridLayoutManager(this@SortingActivity, columns)
|
||||||
sizeSortAdapter?.setColumns(columns)
|
sizeSortAdapter?.setColumns(columns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -654,10 +660,10 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
private fun startFilter() {
|
private fun startFilter() {
|
||||||
Common.showLog("--------------开始筛选")
|
Common.showLog("--------------开始筛选")
|
||||||
|
|
||||||
val filterSizeCovert = filterSizeCovert(scanType, filterSize)
|
val filterSizeCovert = filterSizeCovert(fileType, filterSize)
|
||||||
when (binding.recyclerView.adapter) {
|
when (binding.recyclerView.adapter) {
|
||||||
//当前是时间排序
|
//当前是时间排序
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
//确定当前排序
|
//确定当前排序
|
||||||
val list = if (sortReverse) sortByDateReverse else sortedByDatePositive
|
val list = if (sortReverse) sortByDateReverse else sortedByDatePositive
|
||||||
list.filterWithinDateRange(
|
list.filterWithinDateRange(
|
||||||
@ -665,8 +671,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
||||||
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
||||||
).run {
|
).run {
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.PHOTO,FileType.DOCUMENT -> {
|
||||||
filterBySize(filterSizeCovert.first, filterSizeCovert.second)
|
filterBySize(filterSizeCovert.first, filterSizeCovert.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,15 +690,15 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
//当前是大小排序
|
//当前是大小排序
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
val list = if (sortReverse) sortBySizeBigToSmall else sortBySizeSmallToBig
|
val list = if (sortReverse) sortBySizeBigToSmall else sortBySizeSmallToBig
|
||||||
list.filterWithinDateRangeList(
|
list.filterWithinDateRangeList(
|
||||||
filterDate,
|
filterDate,
|
||||||
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
startDate = if (filterDate == FILTER_DATE_CUSTOMER) filterStartDate else null,
|
||||||
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
endDate = if (filterDate == FILTER_DATE_CUSTOMER) filterEndDate else null
|
||||||
).run {
|
).run {
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
FileType.PHOTO,FileType.DOCUMENT-> {
|
||||||
filterBySizeList(filterSizeCovert.first, filterSizeCovert.second)
|
filterBySizeList(filterSizeCovert.first, filterSizeCovert.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,9 +742,9 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun filterSizeCovert(scanType: Int, filterSize: String): Pair<Long, Long> {
|
private fun filterSizeCovert(fileType: FileType, filterSize: String): Pair<Long, Long> {
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
FileType.PHOTO -> {
|
||||||
val stringArray = resources.getStringArray(R.array.filter_size_photo)
|
val stringArray = resources.getStringArray(R.array.filter_size_photo)
|
||||||
return when (filterSize) {
|
return when (filterSize) {
|
||||||
stringArray[0] -> Pair(-1L, -1L)
|
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)
|
val stringArray = resources.getStringArray(R.array.filter_duration_video_audio)
|
||||||
return when (filterSize) {
|
return when (filterSize) {
|
||||||
stringArray[0] -> Pair(-1L, -1L)
|
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)
|
val stringArray = resources.getStringArray(R.array.filter_documents_size)
|
||||||
return when (filterSize) {
|
return when (filterSize) {
|
||||||
stringArray[0] -> Pair(-1L, -1L)
|
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 删除
|
* @param type 0 恢复 1 删除
|
||||||
*/
|
*/
|
||||||
private fun complete(number: Int, type: Int) {
|
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_COUNT, number)
|
||||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
||||||
|
putExtra(Common.KEY_FILE_TYPE, fileType.value)
|
||||||
})
|
})
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@ -1019,11 +1025,11 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
private fun checkTypeAfter(onAction: (isDateSort: Boolean) -> Unit) {
|
private fun checkTypeAfter(onAction: (isDateSort: Boolean) -> Unit) {
|
||||||
when (binding.recyclerView.adapter) {
|
when (binding.recyclerView.adapter) {
|
||||||
is PhotoDisplayDateAdapter -> {
|
is SortDisplayAdapter -> {
|
||||||
onAction(true)
|
onAction(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
is PhotoDisplayDateChildAdapter -> {
|
is SortDisplayChildAdapter -> {
|
||||||
onAction(false)
|
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.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
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.db.ResultDataFiles
|
||||||
|
import com.ux.video.file.filerecovery.result.ScanResultRepository
|
||||||
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
|
||||||
|
class SortingViewModel : ViewModel() {
|
||||||
class ScanRepository : ViewModel() {
|
|
||||||
// private val _selectedFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
// private val _selectedFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
||||||
// val selectedFlow: StateFlow<MutableSet<String>> = _selectedFlow
|
// val selectedFlow: StateFlow<MutableSet<String>> = _selectedFlow
|
||||||
//
|
//
|
||||||
@ -14,7 +16,7 @@ class ScanRepository : ViewModel() {
|
|||||||
// private val _selectedDisplayFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
// private val _selectedDisplayFlow = MutableStateFlow<MutableSet<String>>(mutableSetOf())
|
||||||
// val selectedDisplayFlow: StateFlow<MutableSet<String>> = _selectedDisplayFlow
|
// val selectedDisplayFlow: StateFlow<MutableSet<String>> = _selectedDisplayFlow
|
||||||
|
|
||||||
|
val sortingData: MutableLiveData<List<ResultDataFiles>> = ScanResultRepository.sortingData
|
||||||
|
|
||||||
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
|
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 selected = _selectedLiveData.value.orEmpty().toMutableSet()
|
||||||
val display = _selectedDisplayLiveData.value.orEmpty().toMutableSet()
|
val display = _selectedDisplayLiveData.value.orEmpty().toMutableSet()
|
||||||
|
|
||||||
@ -1,36 +1,15 @@
|
|||||||
package com.ux.video.file.filerecovery.success
|
package com.ux.video.file.filerecovery.success
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Environment
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseActivity
|
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityRecoverOrDeletedSuccessBinding
|
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.MainActivity
|
||||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_AUDIO
|
import com.ux.video.file.filerecovery.recovery.RecoveryActivity
|
||||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
|
||||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_PHOTO
|
|
||||||
import com.ux.video.file.filerecovery.main.ScanSelectTypeActivity.Companion.VALUE_VIDEO
|
|
||||||
import com.ux.video.file.filerecovery.result.ScanResultDisplayActivity
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
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.FileType
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_audio
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_photo
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_video
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_photo
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_video
|
|
||||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
|
||||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
|
||||||
import com.ux.video.file.filerecovery.utils.ScanState
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBinding>() {
|
class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBinding>() {
|
||||||
|
|
||||||
@ -39,7 +18,7 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
|||||||
val KEY_SUCCESS_COUNT = "success_count"
|
val KEY_SUCCESS_COUNT = "success_count"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
private lateinit var fileType: FileType
|
||||||
|
|
||||||
//0 恢复成功 1 删除成功
|
//0 恢复成功 1 删除成功
|
||||||
private var successType = 0
|
private var successType = 0
|
||||||
@ -48,7 +27,10 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
|||||||
|
|
||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.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)
|
successType = intent.getIntExtra(KEY_SUCCESS_TYPE, 0)
|
||||||
val counts = intent.getIntExtra(KEY_SUCCESS_COUNT, 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)
|
tvLeft.text = resources.getString(R.string.text_continue)
|
||||||
tvRight.text = resources.getString(R.string.view)
|
tvRight.text = resources.getString(R.string.view)
|
||||||
}
|
}
|
||||||
when (scanType) {
|
when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> tvFileType.text =
|
FileType.PHOTO -> tvFileType.text =
|
||||||
resources.getString(R.string.describe_photos)
|
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)
|
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)
|
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)
|
resources.getString(R.string.describe_documents)
|
||||||
}
|
}
|
||||||
when (successType) {
|
when (successType) {
|
||||||
@ -86,7 +68,13 @@ class RecoverySuccessActivity : BaseActivity<ActivityRecoverOrDeletedSuccessBind
|
|||||||
|
|
||||||
bottomBtnRecoverLayout.tvLeft.setOnClickListener { finish()}
|
bottomBtnRecoverLayout.tvLeft.setOnClickListener { finish()}
|
||||||
bottomBtnRecoverLayout.tvRight.setOnClickListener {
|
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.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import android.icu.text.SimpleDateFormat
|
import android.icu.text.SimpleDateFormat
|
||||||
import android.icu.util.Calendar
|
import android.icu.util.Calendar
|
||||||
import android.media.MediaMetadataRetriever
|
import android.media.MediaMetadataRetriever
|
||||||
@ -11,34 +13,24 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
|
import com.ux.video.file.filerecovery.utils.ScanManager.getVideoResolution
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.collections.sortedBy
|
|
||||||
|
|
||||||
object Common {
|
object Common {
|
||||||
|
|
||||||
val itemSpacing = 10
|
val itemSpacing = 10
|
||||||
val horizontalSpacing = 16
|
val horizontalSpacing = 16
|
||||||
|
|
||||||
val KEY_SCAN_TYPE = "scan_type"
|
val KEY_SCAN_TYPE = "key_scan_type"
|
||||||
val VALUE_SCAN_TYPE_photo = 0
|
val KEY_FILE_TYPE = "key_file_type"
|
||||||
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 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
|
if (filtered.isNotEmpty()) key to filtered else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchByNameList(
|
fun searchByNameList(
|
||||||
list: List<ResultDataFiles>,
|
list: List<ResultDataFiles>,
|
||||||
keyword: String
|
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(
|
fun removeSelectedFromList(
|
||||||
@ -294,12 +274,12 @@ object Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getMediaDuration(filePath: String): Long {
|
fun getMediaDuration(filePath: String): Long {
|
||||||
val retriever = MediaMetadataRetriever()
|
val retriever = MediaMetadataRetriever()
|
||||||
return try {
|
return try {
|
||||||
retriever.setDataSource(filePath)
|
retriever.setDataSource(filePath)
|
||||||
val durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
val durationStr =
|
||||||
|
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
||||||
durationStr?.toLongOrNull() ?: 0L // 单位:毫秒
|
durationStr?.toLongOrNull() ?: 0L // 单位:毫秒
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@ -323,6 +303,7 @@ object Common {
|
|||||||
String.format("%02d:%02d", minutes, seconds)
|
String.format("%02d:%02d", minutes, seconds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFileMIME(file: File): String {
|
fun getFileMIME(file: File): String {
|
||||||
val ext = file.extension.lowercase()
|
val ext = file.extension.lowercase()
|
||||||
val mimeTypeFromExtension = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
val mimeTypeFromExtension = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
||||||
@ -340,6 +321,7 @@ object Common {
|
|||||||
mime == "application/zip" ||
|
mime == "application/zip" ||
|
||||||
mime == "application/x-rar-compressed" ||
|
mime == "application/x-rar-compressed" ||
|
||||||
mime == "application/x-7z-compressed" -> "archive"
|
mime == "application/x-7z-compressed" -> "archive"
|
||||||
|
|
||||||
else -> "other"
|
else -> "other"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,9 +330,11 @@ object Common {
|
|||||||
"xapk" to "application/zip",
|
"xapk" to "application/zip",
|
||||||
// 可以继续添加其他自定义扩展名
|
// 可以继续添加其他自定义扩展名
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getMimeTypeParts(file: File): String {
|
fun getMimeTypeParts(file: File): String {
|
||||||
val extension = file.extension.lowercase()
|
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}")
|
showLog("-----------ext=$extension mimeType=${mimeType}")
|
||||||
return if (mimeType != null && mimeType.contains("/")) {
|
return if (mimeType != null && mimeType.contains("/")) {
|
||||||
val parts = mimeType.split("/")
|
val parts = mimeType.split("/")
|
||||||
@ -380,7 +364,8 @@ object Common {
|
|||||||
fun getFormatDate(time: Long): String {
|
fun getFormatDate(time: Long): String {
|
||||||
return dateFormat.format(Date(time))
|
return dateFormat.format(Date(time))
|
||||||
}
|
}
|
||||||
fun getItemMonthDay(time: Long): String{
|
|
||||||
|
fun getItemMonthDay(time: Long): String {
|
||||||
return itemDateFormat.format(time)
|
return itemDateFormat.format(time)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,4 +385,117 @@ object Common {
|
|||||||
fun showLog(msg: String) {
|
fun showLog(msg: String) {
|
||||||
Log.d("============", msg)
|
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 android.util.TypedValue
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -24,6 +26,8 @@ object ExtendFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Parcelable> Intent.getParcelableArrayListExtraCompat(key: String): ArrayList<T>? {
|
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) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
getParcelableArrayListExtra(key, T::class.java)
|
getParcelableArrayListExtra(key, T::class.java)
|
||||||
} else {
|
} else {
|
||||||
@ -134,7 +138,7 @@ object ExtendFunctions {
|
|||||||
maxSize: Long
|
maxSize: Long
|
||||||
): List<ResultDataFiles> {
|
): List<ResultDataFiles> {
|
||||||
if (minSize == -1L) return this
|
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>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
if (minSize == -1L) return this
|
if (minSize == -1L) return this
|
||||||
return this.mapNotNull { (date, files) ->
|
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
|
if (filtered.isNotEmpty()) date to filtered else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +189,7 @@ object ExtendFunctions {
|
|||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
this@filterThumbnailsAsync.asSequence()
|
this@filterThumbnailsAsync.asSequence()
|
||||||
.mapNotNull { (key, files) ->
|
.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
|
if (filtered.isNotEmpty()) key to filtered else null
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
@ -198,7 +202,7 @@ object ExtendFunctions {
|
|||||||
suspend fun List<ResultDataFiles>.filterRemoveThumbnailsAsync(): List<ResultDataFiles> =
|
suspend fun List<ResultDataFiles>.filterRemoveThumbnailsAsync(): List<ResultDataFiles> =
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
this@filterRemoveThumbnailsAsync.asSequence()
|
this@filterRemoveThumbnailsAsync.asSequence()
|
||||||
.filter { !it.isThumbnail } // 去掉 isThumbnail = true 的项
|
.filter { !it.isThumbnail() } // 去掉 isThumbnail = true 的项
|
||||||
.toList()
|
.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
|
package com.ux.video.file.filerecovery.utils
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.media.MediaMetadataRetriever
|
import android.media.MediaMetadataRetriever
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.ux.video.file.filerecovery.db.ResultData
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.currentCoroutineContext
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
@ -56,7 +50,7 @@ object ScanManager {
|
|||||||
context: Context,
|
context: Context,
|
||||||
root: File, maxDepth: Int = 5,
|
root: File, maxDepth: Int = 5,
|
||||||
maxFiles: Int = 5000,
|
maxFiles: Int = 5000,
|
||||||
type: Int
|
fileType: FileType
|
||||||
): Flow<ScanState> = flow {
|
): Flow<ScanState> = flow {
|
||||||
|
|
||||||
val result = mutableMapOf<String, MutableList<File>>()
|
val result = mutableMapOf<String, MutableList<File>>()
|
||||||
@ -71,24 +65,7 @@ object ScanManager {
|
|||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
scanDocuments(file, depth + 1)
|
scanDocuments(file, depth + 1)
|
||||||
} else {
|
} else {
|
||||||
var fileCheckBoolean: Boolean = false
|
val fileCheckBoolean: Boolean = checkFileFormat(file,fileType)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fileCheckBoolean) {
|
if (fileCheckBoolean) {
|
||||||
val dirName = file.parentFile?.name ?: "Unknown"
|
val dirName = file.parentFile?.name ?: "Unknown"
|
||||||
|
|
||||||
@ -114,8 +91,7 @@ object ScanManager {
|
|||||||
file.length()
|
file.length()
|
||||||
),
|
),
|
||||||
lastModified = file.lastModified(),
|
lastModified = file.lastModified(),
|
||||||
resolution = getResolution(type, file),
|
fileType = fileType
|
||||||
fileType = getFileType(type)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ResultData(dir, ArrayList(resultDataFilesList))
|
ResultData(dir, ArrayList(resultDataFilesList))
|
||||||
@ -159,9 +135,9 @@ object ScanManager {
|
|||||||
fun scanHiddenPhotoAsync(
|
fun scanHiddenPhotoAsync(
|
||||||
context: Context,
|
context: Context,
|
||||||
root: File, maxDepth: Int = 5,
|
root: File, maxDepth: Int = 5,
|
||||||
maxFiles: Int = 5000, type: Int
|
maxFiles: Int = 5000, fileType: FileType
|
||||||
): Flow<ScanState> = flow {
|
): Flow<ScanState> = flow {
|
||||||
|
// scanRecycler(context)
|
||||||
val result = mutableMapOf<String, MutableList<File>>()
|
val result = mutableMapOf<String, MutableList<File>>()
|
||||||
var fileCount = 0
|
var fileCount = 0
|
||||||
|
|
||||||
@ -169,46 +145,52 @@ object ScanManager {
|
|||||||
suspend fun scanDir(dir: File, depth: Int, insideHidden: Boolean = false) {
|
suspend fun scanDir(dir: File, depth: Int, insideHidden: Boolean = false) {
|
||||||
if (!dir.exists() || !dir.isDirectory) return
|
if (!dir.exists() || !dir.isDirectory) return
|
||||||
if (depth > maxDepth || fileCount >= maxFiles) 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")
|
showLog("HiddenScan", "${dir.name} 111111")
|
||||||
|
|
||||||
dir.listFiles()?.forEach { file ->
|
dir.listFiles()?.forEach { file ->
|
||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
val isHidden = file.name.startsWith(".")
|
val isHidden = file.name.startsWith(".")
|
||||||
scanDir(file, depth + 1, insideHidden = insideHidden || isHidden)
|
scanDir(file, depth + 1, insideHidden = insideHidden || isHidden)
|
||||||
} else {
|
} else {
|
||||||
|
val fileCheckBoolean: Boolean = checkFileFormat(file,fileType)
|
||||||
if (insideHidden) {
|
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) {
|
if (fileCheckBoolean) {
|
||||||
val dirName = file.parentFile?.name ?: "Unknown"
|
val dirName = file.parentFile?.name ?: "Unknown"
|
||||||
ScanManager.showLog("HiddenScan", "${dirName} 22222")
|
ScanManager.showLog("HiddenScan", "${dirName} 22222 ${file.name}")
|
||||||
val list = result.getOrPut(dirName) { mutableListOf() }
|
val list = result.getOrPut(dirName) { mutableListOf() }
|
||||||
list.add(file)
|
list.add(file)
|
||||||
fileCount++
|
fileCount++
|
||||||
emit(ScanState.Progress(fileCount, file.absolutePath))
|
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)
|
scanDir(root, depth = 0)
|
||||||
ScanManager.showLog("HiddenScan", " 3333")
|
ScanManager.showLog("HiddenScan", " 44444444")
|
||||||
val map = result.map { (dir, files) ->
|
val map = result.map { (dir, files) ->
|
||||||
val resultDataFilesList = files.map { file ->
|
val resultDataFilesList = files.map { file ->
|
||||||
ResultDataFiles(
|
ResultDataFiles(
|
||||||
@ -220,8 +202,7 @@ object ScanManager {
|
|||||||
file.length()
|
file.length()
|
||||||
),
|
),
|
||||||
lastModified = file.lastModified(),
|
lastModified = file.lastModified(),
|
||||||
resolution = getResolution(type, file),
|
fileType = fileType
|
||||||
fileType = getFileType(type)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -231,17 +212,63 @@ object ScanManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getFileType(scanType: Int): Int {
|
private fun checkFileFormat(file: File, fileType: FileType): Boolean {
|
||||||
return when (scanType) {
|
return when (fileType) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> 0
|
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
|
FileType.AUDIO -> {
|
||||||
VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> 3
|
isFormatFile(file, AUDIO_FILE)
|
||||||
else -> 3
|
}
|
||||||
|
|
||||||
|
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 {
|
private fun getFileSizeByMediaStore(context: Context, file: File): Long {
|
||||||
val uri = Uri.fromFile(file)
|
val uri = Uri.fromFile(file)
|
||||||
@ -255,23 +282,24 @@ object ScanManager {
|
|||||||
return file.length() // fallback
|
return file.length() // fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getResolution(type: Int, file: File): String {
|
// private fun getResolution(type: Int, file: File): String {
|
||||||
return when (type) {
|
// return when (type) {
|
||||||
VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
// VALUE_SCAN_TYPE_photo, VALUE_SCAN_TYPE_deleted_photo -> {
|
||||||
getImageSize(file).run {
|
// getImageSize(file).run {
|
||||||
"$first*$second"
|
// "$first*$second"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> getVideoResolution(file.path).run {
|
// VALUE_SCAN_TYPE_video, VALUE_SCAN_TYPE_deleted_video -> getVideoResolution(file.path).run {
|
||||||
"$first*$second"
|
// "$first*$second"
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
else -> ""
|
// else -> ""
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun isFormatFile(file: File, types: List<String>): Boolean {
|
private fun isFormatFile(file: File, types: List<String>): Boolean {
|
||||||
|
if (!file.exists() || file.length() <= 0) return false
|
||||||
val ext = file.extension.lowercase()
|
val ext = file.extension.lowercase()
|
||||||
return types.contains(ext)
|
return types.contains(ext)
|
||||||
}
|
}
|
||||||
@ -284,6 +312,7 @@ object ScanManager {
|
|||||||
Log.d(tag, msg)
|
Log.d(tag, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isValidImage(file: File): Boolean {
|
fun isValidImage(file: File): Boolean {
|
||||||
if (!file.exists() || file.length() <= 0) return false
|
if (!file.exists() || file.length() <= 0) return false
|
||||||
return try {
|
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.databinding.ActivityVideoPlayBinding
|
||||||
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
||||||
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
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.success.RecoverySuccessActivity
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
import com.ux.video.file.filerecovery.utils.FileType
|
||||||
|
|
||||||
class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
|||||||
binding.run {
|
binding.run {
|
||||||
myData?.let { resultPhotosFiles->
|
myData?.let { resultPhotosFiles->
|
||||||
imageBack.setOnClickListener { finish() }
|
imageBack.setOnClickListener { finish() }
|
||||||
resultPhotosFiles.targetFile?.let {
|
resultPhotosFiles.targetFile().let {
|
||||||
PlayMediaManager(context = this@VideoPlayActivity, mediaFile = it, playView = playerView,
|
PlayMediaManager(context = this@VideoPlayActivity, mediaFile = it, playView = playerView,
|
||||||
seekBar = seekBar, playBtn = playImage, onUpdateProgress = { current,total->
|
seekBar = seekBar, playBtn = playImage, onUpdateProgress = { current,total->
|
||||||
textTimeCurrent.text = current
|
textTimeCurrent.text = current
|
||||||
@ -141,7 +143,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
|||||||
myData?.let {
|
myData?.let {
|
||||||
player = ExoPlayer.Builder(this).build()
|
player = ExoPlayer.Builder(this).build()
|
||||||
binding.playerView.player = player
|
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 {
|
player.addListener(object : Player.Listener {
|
||||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
super.onPlaybackStateChanged(playbackState)
|
super.onPlaybackStateChanged(playbackState)
|
||||||
@ -177,6 +179,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
|||||||
startActivity(Intent(this@VideoPlayActivity, RecoverySuccessActivity::class.java).apply {
|
startActivity(Intent(this@VideoPlayActivity, RecoverySuccessActivity::class.java).apply {
|
||||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_COUNT, number)
|
putExtra(RecoverySuccessActivity.KEY_SUCCESS_COUNT, number)
|
||||||
putExtra(RecoverySuccessActivity.KEY_SUCCESS_TYPE, type)
|
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:layout_height="match_parent"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".sort.PhotoInfoActivity">
|
tools:context=".detail.DetailsActivity">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -27,6 +27,7 @@
|
|||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:src="@drawable/ic_setting"
|
android:src="@drawable/ic_setting"
|
||||||
|
android:id="@+id/im_setting"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
app:layout_constraintBottom_toBottomOf="@id/tv_title"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
app:layout_constraintTop_toTopOf="@id/tv_title" />
|
||||||
@ -186,7 +187,7 @@
|
|||||||
android:id="@+id/layout_recovery"
|
android:id="@+id/layout_recovery"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:background="@drawable/main_type_bg"
|
android:background="@drawable/main_type_bg"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
@ -219,6 +220,7 @@
|
|||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginStart="11dp"
|
android:layout_marginStart="11dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
|
android:visibility="gone"
|
||||||
android:background="@drawable/main_type_bg"
|
android:background="@drawable/main_type_bg"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@ -243,66 +245,8 @@
|
|||||||
app:fontType="bold" />
|
app:fontType="bold" />
|
||||||
</LinearLayout>
|
</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>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@ -7,7 +7,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context=".sort.PhotoSortingActivity">
|
tools:context=".sort.SortingActivity">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/layout_top"
|
android:id="@+id/layout_top"
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".documents.DocumentsScanResultActivity">
|
tools:context=".settings.PrivacyPolicyActivity">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/selector_recovery_file_tab_layout_title"
|
android:textColor="@color/selector_recovery_file_tab_layout_title"
|
||||||
android:textSize="15sp"
|
android:textSize="13sp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
app:fontType="bold" />
|
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="view_div_color">#D9D9D9</color>
|
||||||
<color name="bg_seekbar_video_play">#99F2F2F7</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>
|
</resources>
|
||||||
@ -1,10 +1,13 @@
|
|||||||
<resources>
|
<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_all_file">Scan all files</string>
|
||||||
<string name="scan_deleted_files">Scan deleted files</string>
|
<string name="scan_deleted_files">Scan deleted files</string>
|
||||||
<string name="select_all">Select all</string>
|
<string name="select_all">Select all</string>
|
||||||
<string name="select">Select</string>
|
<string name="select">Select</string>
|
||||||
<string name="deselect_all">Deselect all</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>
|
<string name="size_kb">%.2f KB</string>
|
||||||
@ -29,7 +32,7 @@
|
|||||||
<string name="audio_title">Audio recovery</string>
|
<string name="audio_title">Audio recovery</string>
|
||||||
<string name="document_title">Document 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">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="permission_request_promote">We will never share, upload, or send your data without your permission.</string>
|
||||||
|
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
@ -88,7 +91,7 @@ wait..</string>
|
|||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
<string name="recovered_files">Recovered files</string>
|
<string name="recovered_files">Recovered files</string>
|
||||||
<string name="text_counts">(%d)</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>
|
All Recovery to avoid file loss.</string>
|
||||||
<string name="no_files">No files have been recovered yet~</string>
|
<string name="no_files">No files have been recovered yet~</string>
|
||||||
<string name="scan_photos">Scan photos</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_audios">Scan audios</string>
|
||||||
<string name="scan_documents">Scan documents</string>
|
<string name="scan_documents">Scan documents</string>
|
||||||
<string name="share_placeholder">Share (%d)</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">
|
<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 {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
alias(libs.plugins.kotlin.android) 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 {
|
buildscript {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("io.objectbox:objectbox-gradle-plugin:4.0.3")
|
classpath("io.objectbox:objectbox-gradle-plugin:5.0.1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,3 +21,6 @@ kotlin.code.style=official
|
|||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# 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