增加数据库
@ -3,6 +3,7 @@ plugins {
|
|||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -47,6 +48,9 @@ dependencies {
|
|||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.constraintlayout)
|
implementation(libs.androidx.constraintlayout)
|
||||||
|
implementation(libs.androidx.lifecycle.livedata.ktx)
|
||||||
|
implementation(libs.androidx.lifecycle.viewmodel.ktx)
|
||||||
|
implementation(libs.androidx.fragment.ktx)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|||||||
78
app/objectbox-models/default.json
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
|
||||||
|
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
|
||||||
|
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"id": "2:1219714858038066790",
|
||||||
|
"lastPropertyId": "8:5134665607056785092",
|
||||||
|
"name": "ResultDataFiles",
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "1:1863268749092884504",
|
||||||
|
"name": "id",
|
||||||
|
"type": 6,
|
||||||
|
"flags": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2:685886748782553244",
|
||||||
|
"name": "fileType",
|
||||||
|
"type": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3:313976899017664946",
|
||||||
|
"name": "name",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4:3491625332486824618",
|
||||||
|
"name": "path",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5:2788384583815433725",
|
||||||
|
"name": "size",
|
||||||
|
"type": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6:8902434027574194684",
|
||||||
|
"name": "sizeString",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7:8305655849151310709",
|
||||||
|
"name": "lastModified",
|
||||||
|
"type": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8:5134665607056785092",
|
||||||
|
"name": "resolution",
|
||||||
|
"type": 9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relations": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastEntityId": "2:1219714858038066790",
|
||||||
|
"lastIndexId": "0:0",
|
||||||
|
"lastRelationId": "0:0",
|
||||||
|
"lastSequenceId": "0:0",
|
||||||
|
"modelVersion": 5,
|
||||||
|
"modelVersionParserMinimum": 5,
|
||||||
|
"retiredEntityUids": [
|
||||||
|
4830032338777965154
|
||||||
|
],
|
||||||
|
"retiredIndexUids": [],
|
||||||
|
"retiredPropertyUids": [
|
||||||
|
7967846713481917737,
|
||||||
|
5916406351352231902,
|
||||||
|
5265574492754659377,
|
||||||
|
1284016652408596993,
|
||||||
|
3831579248666795267,
|
||||||
|
4445203567182319472,
|
||||||
|
6858261029979256233,
|
||||||
|
2835789057594891780
|
||||||
|
],
|
||||||
|
"retiredRelationUids": [],
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@ -2,12 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Android 10 及以下 -->
|
<!-- Android 10 及以下 -->
|
||||||
<uses-permission
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 11+ -->
|
||||||
android:maxSdkVersion="28" />
|
|
||||||
<uses-permission
|
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
|
||||||
android:maxSdkVersion="28" /> <!-- Android 11+ -->
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||||
tools:ignore="ScopedStorage" />
|
tools:ignore="ScopedStorage" />
|
||||||
@ -24,14 +20,17 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.FileRecovery"
|
android:theme="@style/Theme.FileRecovery"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".recovery.RecoveryActivity"
|
||||||
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".video.VideoPlayActivity"
|
android:name=".video.VideoPlayActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".photo.PhotoInfoActivity"
|
android:name=".sort.PhotoInfoActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".photo.PhotoSortingActivity"
|
android:name=".sort.PhotoSortingActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".result.ScanResultDisplayActivity"
|
android:name=".result.ScanResultDisplayActivity"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.ux.video.file.filerecovery
|
package com.ux.video.file.filerecovery
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
||||||
import org.jaaksi.pickerview.widget.BasePickerView
|
import org.jaaksi.pickerview.widget.BasePickerView
|
||||||
|
|
||||||
class App: Application() {
|
class App: Application() {
|
||||||
@ -14,5 +15,6 @@ class App: Application() {
|
|||||||
|
|
||||||
BasePickerView.sDefaultItemSize = 40
|
BasePickerView.sDefaultItemSize = 40
|
||||||
// BasePickerView.sDefaultDrawIndicator = false
|
// BasePickerView.sDefaultDrawIndicator = false
|
||||||
|
ObjectBoxManager.initObjectBoxDb(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.ux.video.file.filerecovery.base
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.viewbinding.ViewBinding
|
||||||
|
|
||||||
|
abstract class BaseFragment<T : ViewBinding> : Fragment() {
|
||||||
|
|
||||||
|
protected lateinit var binding: T
|
||||||
|
|
||||||
|
abstract fun initBinding(inflater: LayoutInflater, container: ViewGroup?): T
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = initBinding(inflater,container)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,144 @@
|
|||||||
|
package com.ux.video.file.filerecovery.db
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
|
|
||||||
|
import io.objectbox.Box
|
||||||
|
import io.objectbox.BoxStore
|
||||||
|
import io.objectbox.config.DebugFlags
|
||||||
|
import io.objectbox.reactive.DataSubscription
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlin.jvm.java
|
||||||
|
|
||||||
|
object ObjectBoxManager {
|
||||||
|
val pageSize = 10
|
||||||
|
|
||||||
|
lateinit var objectboxStore: BoxStore
|
||||||
|
|
||||||
|
|
||||||
|
var AllRecoveryBox: Box<ResultDataFiles>? = null
|
||||||
|
|
||||||
|
|
||||||
|
val observer: DataSubscription? = null
|
||||||
|
|
||||||
|
|
||||||
|
fun initObjectBoxDb(context: Context) {
|
||||||
|
objectboxStore = MyObjectBox.builder().androidContext(context)
|
||||||
|
.debugFlags(DebugFlags.LOG_QUERIES or DebugFlags.LOG_QUERY_PARAMETERS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDataBox(): Box<ResultDataFiles> {
|
||||||
|
AllRecoveryBox =
|
||||||
|
AllRecoveryBox ?: objectboxStore.boxFor<ResultDataFiles>(ResultDataFiles::class.java)
|
||||||
|
|
||||||
|
return AllRecoveryBox!!
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun getLikeBox(): Box<ResultPhotosFiles>? {
|
||||||
|
// likeWallpaperBox = likeWallpaperBox ?: boxStore?.boxFor<LikeWallpaper>(ResultPhotosFiles::class.java)
|
||||||
|
// return likeWallpaperBox
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun setLikeUpdateListener(queryAllLike:(List<LikeWallpaper>)->Unit): DataSubscription {
|
||||||
|
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||||
|
// val build: Query<LikeWallpaper> = likeBox!!.query()
|
||||||
|
// .build()
|
||||||
|
// return build.subscribe(DataSubscriptionList())
|
||||||
|
// .on(AndroidScheduler.mainThread())
|
||||||
|
// .observer { data ->
|
||||||
|
// Helper.showMyLog("---OnLikeUpdateListener-------------" + data.size)
|
||||||
|
// queryAllLike(data)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
fun addRecoveryFile(resultData: ResultDataFiles) {
|
||||||
|
val objectBox: Box<ResultDataFiles> = getDataBox()
|
||||||
|
val first = objectBox.query(ResultDataFiles_.path.equal(resultData.path))
|
||||||
|
.build().findFirst()
|
||||||
|
if (first == null) {
|
||||||
|
objectBox.put(resultData)
|
||||||
|
Common.showLog("----------addRecoveryFile----${resultData.path}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// fun insertLike(favoriteData: LikeWallpaper) {
|
||||||
|
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||||
|
// val first: LikeWallpaper? = likeBox!!.query()
|
||||||
|
// .equal(LikeWallpaper_.id, favoriteData.id)
|
||||||
|
// .build()
|
||||||
|
// .findFirst()
|
||||||
|
// if (first == null) {
|
||||||
|
// Helper.showMyLog("---insertLike-----------------id=" + favoriteData.id)
|
||||||
|
// likeBox.put(favoriteData)
|
||||||
|
// } else {
|
||||||
|
// Helper.showMyLog("---insertLike-----------------id=" + favoriteData.id)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
fun deleteRecoveryFile(resultData: ResultDataFiles) {
|
||||||
|
val objectBox = getDataBox()
|
||||||
|
val first =
|
||||||
|
objectBox.query(ResultDataFiles_.path.equal(resultData.path)).build().findFirst()
|
||||||
|
|
||||||
|
if (first != null) {
|
||||||
|
val remove = objectBox.remove(first.id)
|
||||||
|
Common.showLog("----------addRecoveryFile---删除${remove}-${resultData.path}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// fun queryIsLike(id: Long): Boolean {
|
||||||
|
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||||
|
// val first: LikeWallpaper? = likeBox!!.query()
|
||||||
|
// .equal(LikeWallpaper_.id, id)
|
||||||
|
// .build()
|
||||||
|
// .findFirst()
|
||||||
|
// return first != null
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
fun queryRecoveryFile(type: Int): List<ResultDataFiles> {
|
||||||
|
val dataBox = getDataBox()
|
||||||
|
val list: List<ResultDataFiles> = dataBox.query(ResultDataFiles_.fileType.equal(type))
|
||||||
|
.build()
|
||||||
|
.find()
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun queryRecoveryFileAsync(type: Int): List<ResultDataFiles> =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val dataBox = getDataBox()
|
||||||
|
dataBox.query(ResultDataFiles_.fileType.equal(type))
|
||||||
|
.build()
|
||||||
|
.find()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// fun queryLike(currentPage: Int): List<LikeWallpaper> {
|
||||||
|
// val offset: Int = (currentPage - 1) * pageSize
|
||||||
|
// val likeBox: Box<LikeWallpaper>? = getLikeBox()
|
||||||
|
// val data: List<LikeWallpaper> = likeBox!!.query()
|
||||||
|
// .build()
|
||||||
|
// .find(offset.toLong(), pageSize.toLong())
|
||||||
|
//
|
||||||
|
// return data
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun queryAllData(wallpaperType: Long): List<VideoWallpaper> {
|
||||||
|
// val objectBoxLike: Box<VideoWallpaper>? = getDataBox()
|
||||||
|
// val data: List<VideoWallpaper> = objectBoxLike!!.query()
|
||||||
|
// .equal(VideoWallpaper_.wallpapertype, wallpaperType)
|
||||||
|
// .build()
|
||||||
|
// .find()
|
||||||
|
//
|
||||||
|
// return data
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -1,11 +1,11 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.db
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class ResultPhotos(
|
data class ResultData(
|
||||||
val dirName: String,
|
val dirName: String,
|
||||||
val allFiles: ArrayList<ResultPhotosFiles>
|
val allFiles: ArrayList<ResultDataFiles>
|
||||||
): Parcelable
|
): Parcelable
|
||||||
@ -1,15 +1,22 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.db
|
||||||
|
|
||||||
import java.io.File
|
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 io.objectbox.annotation.Entity
|
||||||
|
import io.objectbox.annotation.Id
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Entity
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class ResultPhotosFiles(
|
data class ResultDataFiles(
|
||||||
|
@Id
|
||||||
|
var id: Long = 0,
|
||||||
|
// 0-3 photo\video\audio\documents
|
||||||
|
var fileType: Int,
|
||||||
val name: String,
|
val name: String,
|
||||||
val path: String? = null,
|
val path: String,
|
||||||
val size: Long, // 字节
|
val size: Long, // 字节
|
||||||
val sizeString: String,
|
val sizeString: String,
|
||||||
val lastModified: Long, // 时间戳
|
val lastModified: Long, // 时间戳
|
||||||
@ -36,4 +43,5 @@ data class ResultPhotosFiles(
|
|||||||
val duration: Long
|
val duration: Long
|
||||||
get() {
|
get() {
|
||||||
return Common.getMediaDuration(path.toString()) }
|
return Common.getMediaDuration(path.toString()) }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5,10 +5,10 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.ux.video.file.filerecovery.base.BaseAdapter
|
import com.ux.video.file.filerecovery.base.BaseAdapter
|
||||||
import com.ux.video.file.filerecovery.databinding.DocumentsScanResultAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.DocumentsScanResultAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
|
|
||||||
class DocumentsScanResultAdapter(mContext: Context) :
|
class DocumentsScanResultAdapter(mContext: Context) :
|
||||||
BaseAdapter<ResultPhotos, DocumentsScanResultAdapterBinding>(mContext) {
|
BaseAdapter<ResultData, DocumentsScanResultAdapterBinding>(mContext) {
|
||||||
override fun getViewBinding(parent: ViewGroup): DocumentsScanResultAdapterBinding =
|
override fun getViewBinding(parent: ViewGroup): DocumentsScanResultAdapterBinding =
|
||||||
DocumentsScanResultAdapterBinding.inflate(
|
DocumentsScanResultAdapterBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
@ -18,7 +18,7 @@ class DocumentsScanResultAdapter(mContext: Context) :
|
|||||||
|
|
||||||
override fun bindItem(
|
override fun bindItem(
|
||||||
holder: VHolder<DocumentsScanResultAdapterBinding>,
|
holder: VHolder<DocumentsScanResultAdapterBinding>,
|
||||||
item: ResultPhotos
|
item: ResultData
|
||||||
) {
|
) {
|
||||||
|
|
||||||
holder.vb.run {
|
holder.vb.run {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.ux.video.file.filerecovery.main
|
package com.ux.video.file.filerecovery.main
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@ -20,9 +19,8 @@ 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.main.ScanSelectTypeActivity
|
import com.ux.video.file.filerecovery.recovery.RecoveryActivity
|
||||||
import com.ux.video.file.filerecovery.photo.DateFilterPopupWindows
|
import com.ux.video.file.filerecovery.sort.DatePickerDialogFragment
|
||||||
import com.ux.video.file.filerecovery.photo.DatePickerDialogFragment
|
|
||||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||||
|
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
@ -95,6 +93,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
currentGoType = ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
currentGoType = ScanSelectTypeActivity.Companion.VALUE_DOCUMENT
|
||||||
intentCheck()
|
intentCheck()
|
||||||
}
|
}
|
||||||
|
layoutRecovery.setOnClickListener {
|
||||||
|
startActivity(Intent(this@MainActivity,RecoveryActivity::class.java))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
binding.tvTitle.setOnClickListener {
|
binding.tvTitle.setOnClickListener {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.ux.video.file.filerecovery.recovery
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.ux.video.file.filerecovery.R
|
||||||
|
import com.ux.video.file.filerecovery.base.BaseActivity
|
||||||
|
import com.ux.video.file.filerecovery.databinding.ActivityRecoveryBinding
|
||||||
|
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
||||||
|
import com.ux.video.file.filerecovery.recovery.ui.MyViewPage2Adapter
|
||||||
|
import com.ux.video.file.filerecovery.recovery.ui.recoveryphoto.RecoveryPhotoFragment
|
||||||
|
import com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class RecoveryActivity : BaseActivity<ActivityRecoveryBinding>() {
|
||||||
|
override fun inflateBinding(inflater: LayoutInflater): ActivityRecoveryBinding = ActivityRecoveryBinding.inflate(inflater)
|
||||||
|
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
super.initView()
|
||||||
|
binding.run {
|
||||||
|
|
||||||
|
viewPage2.adapter = MyViewPage2Adapter(this@RecoveryActivity,listOf(RecoveryPhotoFragment(),RecoveryPhotoFragment(),RecoveryPhotoFragment(),RecoveryPhotoFragment()))
|
||||||
|
TabLayoutMediator(tabLayout,viewPage2){tab,position->
|
||||||
|
val tabView = LayoutInflater.from(this@RecoveryActivity).inflate(R.layout.tab_layout_item, null)
|
||||||
|
val tvTitle = tabView.findViewById<CustomTextView>(R.id.tab_item_title)
|
||||||
|
val tvCount = tabView.findViewById<CustomTextView>(R.id.tab_item_count)
|
||||||
|
tvCount.text = getString(R.string.text_counts, 0)
|
||||||
|
when(position){
|
||||||
|
0->{tvTitle.text = getString(R.string.text_photos)}
|
||||||
|
1->{tvTitle.text = getString(R.string.text_videos)}
|
||||||
|
2->{tvTitle.text = getString(R.string.text_audios)}
|
||||||
|
3->{tvTitle.text = getString(R.string.text_documents)}
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.customView = tabView
|
||||||
|
}.attach()
|
||||||
|
tabLayout.addOnTabSelectedListener(object :OnTabSelectedListener{
|
||||||
|
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initData() {
|
||||||
|
super.initData()
|
||||||
|
lifecycleScope.launch{
|
||||||
|
val recoveryFilePhoto = ObjectBoxManager.queryRecoveryFileAsync(0)
|
||||||
|
val recoveryFileVideo = ObjectBoxManager.queryRecoveryFileAsync(1)
|
||||||
|
val recoveryFileAudio = ObjectBoxManager.queryRecoveryFileAsync(2)
|
||||||
|
val recoveryFileDocuments = ObjectBoxManager.queryRecoveryFileAsync(3)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.ux.video.file.filerecovery.recovery.ui
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
|
||||||
|
|
||||||
|
class MyViewPage2Adapter(
|
||||||
|
fragmentActivity: FragmentActivity,
|
||||||
|
private val fragments: List<Fragment>
|
||||||
|
) : FragmentStateAdapter(fragmentActivity) {
|
||||||
|
override fun getItemCount(): Int = fragments.size
|
||||||
|
override fun createFragment(position: Int): Fragment = fragments[position]
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
|
||||||
|
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.ux.video.file.filerecovery.R
|
||||||
|
import com.ux.video.file.filerecovery.base.BaseFragment
|
||||||
|
import com.ux.video.file.filerecovery.databinding.FragmentRecoveryPhotoBinding
|
||||||
|
|
||||||
|
|
||||||
|
class RecoveryPhotoFragment : BaseFragment<FragmentRecoveryPhotoBinding>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = RecoveryPhotoFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val viewModel: RecoveryPhotoViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun initBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRecoveryPhotoBinding =
|
||||||
|
FragmentRecoveryPhotoBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.ux.video.file.filerecovery.recovery.ui.recoveryphoto
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
||||||
|
class RecoveryPhotoViewModel : ViewModel() {
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,9 +7,9 @@ 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.photo.PhotoSortingActivity
|
import com.ux.video.file.filerecovery.sort.PhotoSortingActivity
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.Common.KEY_SCAN_TYPE
|
import com.ux.video.file.filerecovery.utils.Common.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_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_audio
|
||||||
@ -28,7 +28,7 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
|||||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||||
private var exitDialog: ExitDialogFragment? = null
|
private var exitDialog: ExitDialogFragment? = null
|
||||||
|
|
||||||
private var list: ArrayList<ResultPhotos>? = null
|
private var list: ArrayList<ResultData>? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val KEY_SCAN_RESULT = "scan_result"
|
val KEY_SCAN_RESULT = "scan_result"
|
||||||
@ -136,7 +136,7 @@ class ScanResultDisplayActivity : BaseActivity<ActivityScanResultDisplayBinding>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun goSort(list: ArrayList<ResultPhotosFiles>) {
|
private fun goSort(list: ArrayList<ResultDataFiles>) {
|
||||||
startActivity(
|
startActivity(
|
||||||
Intent(
|
Intent(
|
||||||
this@ScanResultDisplayActivity,
|
this@ScanResultDisplayActivity,
|
||||||
|
|||||||
@ -4,20 +4,12 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
|
||||||
import com.bumptech.glide.request.RequestOptions
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.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.ScanResultDocumentsAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.ScanResultDocumentsAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
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.ExtendFunctions.dpToPx
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件或者音频的扫描结果汇总适配器
|
* 文件或者音频的扫描结果汇总适配器
|
||||||
@ -25,9 +17,9 @@ import java.io.File
|
|||||||
class ScanResultDocumentsAdapter(
|
class ScanResultDocumentsAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var type: Int,
|
var type: Int,
|
||||||
var onClickItem: (allFiles: ArrayList<ResultPhotosFiles>) -> Unit
|
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<ResultPhotos, ScanResultDocumentsAdapterBinding>(mContext) {
|
BaseAdapter<ResultData, ScanResultDocumentsAdapterBinding>(mContext) {
|
||||||
override fun getViewBinding(parent: ViewGroup): ScanResultDocumentsAdapterBinding =
|
override fun getViewBinding(parent: ViewGroup): ScanResultDocumentsAdapterBinding =
|
||||||
ScanResultDocumentsAdapterBinding.inflate(
|
ScanResultDocumentsAdapterBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
@ -38,7 +30,7 @@ class ScanResultDocumentsAdapter(
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun bindItem(
|
override fun bindItem(
|
||||||
holder: VHolder<ScanResultDocumentsAdapterBinding>,
|
holder: VHolder<ScanResultDocumentsAdapterBinding>,
|
||||||
item: ResultPhotos
|
item: ResultData
|
||||||
) {
|
) {
|
||||||
|
|
||||||
holder.vb.run {
|
holder.vb.run {
|
||||||
|
|||||||
@ -11,17 +11,17 @@ 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.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.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ScanResultPhotoAdapter(
|
class ScanResultPhotoAdapter(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
var type: Int,
|
var type: Int,
|
||||||
var onClickItem: (allFiles: ArrayList<ResultPhotosFiles>) -> Unit
|
var onClickItem: (allFiles: ArrayList<ResultDataFiles>) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<ResultPhotos, ScanResultAdapterBinding>(mContext) {
|
BaseAdapter<ResultData, ScanResultAdapterBinding>(mContext) {
|
||||||
override fun getViewBinding(parent: ViewGroup): ScanResultAdapterBinding =
|
override fun getViewBinding(parent: ViewGroup): ScanResultAdapterBinding =
|
||||||
ScanResultAdapterBinding.inflate(
|
ScanResultAdapterBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
LayoutInflater.from(parent.context),
|
||||||
@ -32,7 +32,7 @@ class ScanResultPhotoAdapter(
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun bindItem(
|
override fun bindItem(
|
||||||
holder: VHolder<ScanResultAdapterBinding>,
|
holder: VHolder<ScanResultAdapterBinding>,
|
||||||
item: ResultPhotos
|
item: ResultData
|
||||||
) {
|
) {
|
||||||
|
|
||||||
holder.vb.run {
|
holder.vb.run {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
|
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
@ -9,7 +9,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.core.view.forEach
|
|
||||||
import com.ux.video.file.filerecovery.databinding.CommonLayoutFilterItemBinding
|
import com.ux.video.file.filerecovery.databinding.CommonLayoutFilterItemBinding
|
||||||
import com.ux.video.file.filerecovery.databinding.PopwindowsFilterBinding
|
import com.ux.video.file.filerecovery.databinding.PopwindowsFilterBinding
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
@ -1,18 +1,18 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
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.base.DiffBaseAdapter
|
|
||||||
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.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
import com.ux.video.file.filerecovery.utils.GridSpacingItemDecoration
|
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_deleted_documents
|
||||||
|
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_documents
|
||||||
import com.ux.video.file.filerecovery.utils.ScanRepository
|
import com.ux.video.file.filerecovery.utils.ScanRepository
|
||||||
|
|
||||||
class PhotoDisplayDateAdapter(
|
class PhotoDisplayDateAdapter(
|
||||||
@ -20,10 +20,10 @@ class PhotoDisplayDateAdapter(
|
|||||||
var scanType: Int,
|
var scanType: Int,
|
||||||
var mColumns: Int,
|
var mColumns: Int,
|
||||||
var viewModel: ScanRepository,
|
var viewModel: ScanRepository,
|
||||||
var onSelectedUpdate: (resultPhotosFiles: ResultPhotosFiles, isAdd: Boolean) -> Unit,
|
var onSelectedUpdate: (resultDataFiles: ResultDataFiles, isAdd: Boolean) -> Unit,
|
||||||
var clickItem: (item: ResultPhotosFiles) -> Unit
|
var clickItem: (item: ResultDataFiles) -> Unit
|
||||||
) :
|
) :
|
||||||
BaseAdapter<Pair<String, List<ResultPhotosFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
|
BaseAdapter<Pair<String, List<ResultDataFiles>>, PhotoDisplayDateAdapterBinding>(mContext) {
|
||||||
|
|
||||||
|
|
||||||
private var allSelected: Boolean? = null
|
private var allSelected: Boolean? = null
|
||||||
@ -75,7 +75,7 @@ class PhotoDisplayDateAdapter(
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun bindItem(
|
override fun bindItem(
|
||||||
holder: VHolder<PhotoDisplayDateAdapterBinding>,
|
holder: VHolder<PhotoDisplayDateAdapterBinding>,
|
||||||
item: Pair<String, List<ResultPhotosFiles>>
|
item: Pair<String, List<ResultDataFiles>>
|
||||||
) {
|
) {
|
||||||
holder.vb.run {
|
holder.vb.run {
|
||||||
item.run {
|
item.run {
|
||||||
@ -109,9 +109,10 @@ class PhotoDisplayDateAdapter(
|
|||||||
|
|
||||||
recyclerChild.apply {
|
recyclerChild.apply {
|
||||||
layoutManager = when (scanType) {
|
layoutManager = when (scanType) {
|
||||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio -> {
|
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio, VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||||
LinearLayoutManager(context)
|
LinearLayoutManager(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
GridLayoutManager(context, mColumns)
|
GridLayoutManager(context, mColumns)
|
||||||
}
|
}
|
||||||
@ -125,17 +126,17 @@ class PhotoDisplayDateAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ItemDiffCallback : DiffUtil.ItemCallback<Pair<String, List<ResultPhotosFiles>>>() {
|
object ItemDiffCallback : DiffUtil.ItemCallback<Pair<String, List<ResultDataFiles>>>() {
|
||||||
override fun areItemsTheSame(
|
override fun areItemsTheSame(
|
||||||
oldItem: Pair<String, List<ResultPhotosFiles>>,
|
oldItem: Pair<String, List<ResultDataFiles>>,
|
||||||
newItem: Pair<String, List<ResultPhotosFiles>>
|
newItem: Pair<String, List<ResultDataFiles>>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return oldItem.first == newItem.first
|
return oldItem.first == newItem.first
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(
|
override fun areContentsTheSame(
|
||||||
oldItem: Pair<String, List<ResultPhotosFiles>>,
|
oldItem: Pair<String, List<ResultDataFiles>>,
|
||||||
newItem: Pair<String, List<ResultPhotosFiles>>
|
newItem: Pair<String, List<ResultDataFiles>>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return oldItem == newItem
|
return oldItem == newItem
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
@ -7,7 +7,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.DataSource
|
import com.bumptech.glide.load.DataSource
|
||||||
@ -22,7 +21,9 @@ import com.ux.video.file.filerecovery.R
|
|||||||
import com.ux.video.file.filerecovery.base.NewBaseAdapter
|
import com.ux.video.file.filerecovery.base.NewBaseAdapter
|
||||||
import com.ux.video.file.filerecovery.databinding.FileSpanCountThreeAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.FileSpanCountThreeAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.databinding.FileSpanCountTwoAdapterBinding
|
import com.ux.video.file.filerecovery.databinding.FileSpanCountTwoAdapterBinding
|
||||||
import com.ux.video.file.filerecovery.databinding.OneAudioDocumentsItemBinding
|
import com.ux.video.file.filerecovery.databinding.OneAudioItemBinding
|
||||||
|
import com.ux.video.file.filerecovery.databinding.OneDocumentsItemBinding
|
||||||
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.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
|
||||||
@ -40,23 +41,25 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
* @param addOrRemove 选中还是取消选中
|
* @param addOrRemove 选中还是取消选中
|
||||||
* @param dateAllSelected 这组数据是否全部选中(某一天)
|
* @param dateAllSelected 这组数据是否全部选中(某一天)
|
||||||
*/
|
*/
|
||||||
var onSelectedUpdate: (resultPhotosFiles: ResultPhotosFiles, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit,
|
var onSelectedUpdate: (resultDataFiles: ResultDataFiles, addOrRemove: Boolean, dateAllSelected: Boolean) -> Unit,
|
||||||
var hideThumbnailsUpdate: (dateAllSelected: Boolean) -> Unit,
|
var hideThumbnailsUpdate: (dateAllSelected: Boolean) -> Unit,
|
||||||
var clickItem: (item: ResultPhotosFiles) -> Unit
|
var clickItem: (item: ResultDataFiles) -> Unit
|
||||||
) :
|
) :
|
||||||
NewBaseAdapter<ResultPhotosFiles>(mContext) {
|
NewBaseAdapter<ResultDataFiles>(mContext) {
|
||||||
|
|
||||||
|
|
||||||
//日期组某一天的数据选择状态维护
|
//日期组某一天的数据选择状态维护
|
||||||
val dateSelectedMap = mutableSetOf<ResultPhotosFiles>()
|
val dateSelectedMap = mutableSetOf<ResultDataFiles>()
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
//音频或者文档
|
//视频和图片支持布局切换 2/3/4列
|
||||||
private const val TYPE_ONE = 1
|
|
||||||
private const val TYPE_TWO = 2
|
private const val TYPE_TWO = 2
|
||||||
private const val TYPE_THREE = 3
|
private const val TYPE_THREE = 3
|
||||||
private const val TYPE_FOUR = 4
|
private const val TYPE_FOUR = 4
|
||||||
|
|
||||||
|
private const val TYPE_AUDIO = 5
|
||||||
|
private const val TYPE_DOCUMENTS = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setAllSelected(isAdd: Boolean) {
|
fun setAllSelected(isAdd: Boolean) {
|
||||||
@ -69,7 +72,11 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
when (scanType) {
|
when (scanType) {
|
||||||
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio -> {
|
Common.VALUE_SCAN_TYPE_audio, Common.VALUE_SCAN_TYPE_deleted_audio -> {
|
||||||
return TYPE_ONE
|
return TYPE_AUDIO
|
||||||
|
}
|
||||||
|
|
||||||
|
Common.VALUE_SCAN_TYPE_documents, Common.VALUE_SCAN_TYPE_deleted_documents -> {
|
||||||
|
return TYPE_DOCUMENTS
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
@ -110,8 +117,16 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
): RecyclerView.ViewHolder {
|
): RecyclerView.ViewHolder {
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
TYPE_ONE -> OneHolder(
|
TYPE_AUDIO -> AudioHolder(
|
||||||
OneAudioDocumentsItemBinding.inflate(
|
OneAudioItemBinding.inflate(
|
||||||
|
inflater,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
TYPE_DOCUMENTS -> DocumentsHolder(
|
||||||
|
OneDocumentsItemBinding.inflate(
|
||||||
inflater,
|
inflater,
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
@ -139,32 +154,36 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
|
|
||||||
override fun onBind(
|
override fun onBind(
|
||||||
holder: RecyclerView.ViewHolder,
|
holder: RecyclerView.ViewHolder,
|
||||||
item: ResultPhotosFiles,
|
item: ResultDataFiles,
|
||||||
viewType: Int
|
viewType: Int
|
||||||
) {
|
) {
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is TwoHolder -> holder.vb.run {
|
is TwoHolder -> holder.vb.run {
|
||||||
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
|
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ThreeHolder -> holder.vb.run {
|
is ThreeHolder -> holder.vb.run {
|
||||||
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
|
initDateView(rootLayout, imageSelect, textSize, imageThumbnail, item, imageType)
|
||||||
}
|
}
|
||||||
is OneHolder -> {
|
|
||||||
|
is AudioHolder -> {
|
||||||
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
|
||||||
viewModel.checkIsSelect(this).let { isSelected ->
|
|
||||||
it.imageSelect.isSelected = isSelected
|
initAudioDocuments(it.imageSelect,this)
|
||||||
addOrRemove(this, isSelected)
|
// viewModel.checkIsSelect(this).let { isSelected ->
|
||||||
}
|
// it.imageSelect.isSelected = isSelected
|
||||||
it.imageSelect.setOnClickListener {
|
// addOrRemove(this, isSelected)
|
||||||
it.isSelected = !it.isSelected
|
// }
|
||||||
it.isSelected.let { newStatus ->
|
// it.imageSelect.setOnClickListener {
|
||||||
addOrRemove(this, newStatus)
|
// it.isSelected = !it.isSelected
|
||||||
}
|
// it.isSelected.let { newStatus ->
|
||||||
}
|
// addOrRemove(this, newStatus)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
it.constraintLayout.setOnClickListener {
|
it.constraintLayout.setOnClickListener {
|
||||||
clickItem(this)
|
clickItem(this)
|
||||||
}
|
}
|
||||||
@ -172,6 +191,28 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is DocumentsHolder -> {
|
||||||
|
item.run {
|
||||||
|
holder.vb.let {
|
||||||
|
it.textName.text = name
|
||||||
|
it.textDate.text = Common.getItemMonthDay(lastModified)
|
||||||
|
it.textSize.text = sizeString
|
||||||
|
targetFile?.let { file->
|
||||||
|
it.imageIcon.setImageResource(Common.getFileIconRes(file))
|
||||||
|
}
|
||||||
|
|
||||||
|
initAudioDocuments(it.imageSelect,this)
|
||||||
|
|
||||||
|
it.constraintLayout.setOnClickListener {
|
||||||
|
clickItem(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -182,29 +223,45 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
class TwoHolder(val vb: FileSpanCountTwoAdapterBinding) :
|
class TwoHolder(val vb: FileSpanCountTwoAdapterBinding) :
|
||||||
RecyclerView.ViewHolder(vb.root)
|
RecyclerView.ViewHolder(vb.root)
|
||||||
|
|
||||||
class OneHolder(val vb: OneAudioDocumentsItemBinding) :
|
class AudioHolder(val vb: OneAudioItemBinding) :
|
||||||
RecyclerView.ViewHolder(vb.root)
|
RecyclerView.ViewHolder(vb.root)
|
||||||
|
|
||||||
|
class DocumentsHolder(val vb: OneDocumentsItemBinding) :
|
||||||
|
RecyclerView.ViewHolder(vb.root)
|
||||||
|
|
||||||
|
|
||||||
|
private fun initAudioDocuments(imageSelect: ImageView,item: ResultDataFiles){
|
||||||
|
viewModel.checkIsSelect(item).let { isSelected ->
|
||||||
|
imageSelect.isSelected = isSelected
|
||||||
|
addOrRemove(item, isSelected)
|
||||||
|
}
|
||||||
|
imageSelect.setOnClickListener {
|
||||||
|
it.isSelected = !it.isSelected
|
||||||
|
it.isSelected.let { newStatus ->
|
||||||
|
addOrRemove(item, newStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private fun initDateView(
|
private fun initDateView(
|
||||||
rootLayout: RelativeLayout,
|
rootLayout: RelativeLayout,
|
||||||
imageSelectStatus: ImageView,
|
imageSelectStatus: ImageView,
|
||||||
textSize: CustomTextView,
|
textSize: CustomTextView,
|
||||||
imageThumbnail: ImageView,
|
imageThumbnail: ImageView,
|
||||||
item: ResultPhotosFiles,
|
item: ResultDataFiles,
|
||||||
imageType: ImageView
|
imageType: ImageView
|
||||||
) {
|
) {
|
||||||
item.run {
|
item.run {
|
||||||
|
initAudioDocuments(imageSelectStatus,this)
|
||||||
viewModel.checkIsSelect(this).let {
|
// viewModel.checkIsSelect(this).let {
|
||||||
imageSelectStatus.isSelected = it
|
// imageSelectStatus.isSelected = it
|
||||||
addOrRemove(this, it)
|
// addOrRemove(this, it)
|
||||||
}
|
// }
|
||||||
imageSelectStatus.setOnClickListener {
|
// imageSelectStatus.setOnClickListener {
|
||||||
it.isSelected = !it.isSelected
|
// it.isSelected = !it.isSelected
|
||||||
it.isSelected.let { newStatus ->
|
// it.isSelected.let { newStatus ->
|
||||||
addOrRemove(this, newStatus)
|
// addOrRemove(this, newStatus)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
textSize.text = sizeString
|
textSize.text = sizeString
|
||||||
|
|
||||||
imageType.setImageResource(
|
imageType.setImageResource(
|
||||||
@ -254,13 +311,13 @@ class PhotoDisplayDateChildAdapter(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOrRemove(resultPhotosFiles: ResultPhotosFiles, boolean: Boolean) {
|
private fun addOrRemove(resultDataFiles: ResultDataFiles, boolean: Boolean) {
|
||||||
if (boolean) {
|
if (boolean) {
|
||||||
dateSelectedMap.add(resultPhotosFiles)
|
dateSelectedMap.add(resultDataFiles)
|
||||||
} else {
|
} else {
|
||||||
dateSelectedMap.remove(resultPhotosFiles)
|
dateSelectedMap.remove(resultDataFiles)
|
||||||
}
|
}
|
||||||
onSelectedUpdate.invoke(resultPhotosFiles, boolean, dateSelectedMap.size == data.size)
|
onSelectedUpdate.invoke(resultDataFiles, boolean, dateSelectedMap.size == data.size)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,17 +1,13 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.media3.common.MediaItem
|
|
||||||
import androidx.media3.common.Player
|
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.DataSource
|
import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.engine.GlideException
|
import com.bumptech.glide.load.engine.GlideException
|
||||||
@ -23,6 +19,7 @@ import com.bumptech.glide.request.target.Target
|
|||||||
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.ActivityPhotoInfoBinding
|
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.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.KEY_SCAN_TYPE
|
||||||
@ -46,15 +43,15 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
private var scanType: Int = VALUE_SCAN_TYPE_photo
|
||||||
private var myData: ResultPhotosFiles? = null
|
private var myData: ResultDataFiles? = null
|
||||||
private lateinit var player: ExoPlayer
|
|
||||||
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityPhotoInfoBinding =
|
||||||
ActivityPhotoInfoBinding.inflate(inflater)
|
ActivityPhotoInfoBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
super.initView()
|
super.initView()
|
||||||
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
intent.getParcelableExtra(KEY_CLICK_ITEM, ResultPhotosFiles::class.java)
|
intent.getParcelableExtra(KEY_CLICK_ITEM, ResultDataFiles::class.java)
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
intent.getParcelableExtra(KEY_CLICK_ITEM)
|
intent.getParcelableExtra(KEY_CLICK_ITEM)
|
||||||
@ -77,6 +74,9 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
|
|||||||
tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified)
|
tvDate.text = Common.getFormatDate(resultPhotosFiles.lastModified)
|
||||||
tvResolution.text = resultPhotosFiles.resolution
|
tvResolution.text = resultPhotosFiles.resolution
|
||||||
tvDuration.text = Common.formatDuration(resultPhotosFiles.duration)
|
tvDuration.text = Common.formatDuration(resultPhotosFiles.duration)
|
||||||
|
resultPhotosFiles.targetFile?.let {
|
||||||
|
tvType.text = Common.getMimeTypeParts(it)
|
||||||
|
}
|
||||||
layoutBottom.tvLeft.run {
|
layoutBottom.tvLeft.run {
|
||||||
text = resources.getString(R.string.delete)
|
text = resources.getString(R.string.delete)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
@ -161,14 +161,8 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
|
|||||||
layoutSeekbar.isVisible = true
|
layoutSeekbar.isVisible = true
|
||||||
imPlay.isVisible = true
|
imPlay.isVisible = true
|
||||||
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
frameImage.setBackgroundResource(R.drawable.bg_info_music_f2f2f7_8)
|
||||||
image.setImageResource(R.drawable.image_info_music)
|
|
||||||
val params = image.layoutParams ?: ViewGroup.LayoutParams(
|
loadCenterImage(image,R.drawable.image_info_music)
|
||||||
180.dpToPx(this@PhotoInfoActivity),
|
|
||||||
180.dpToPx(this@PhotoInfoActivity)
|
|
||||||
)
|
|
||||||
params.width = 180.dpToPx(this@PhotoInfoActivity)
|
|
||||||
params.height = 180.dpToPx(this@PhotoInfoActivity)
|
|
||||||
image.layoutParams = params
|
|
||||||
|
|
||||||
initPlayAudio()
|
initPlayAudio()
|
||||||
layoutResolution.isVisible = false
|
layoutResolution.isVisible = false
|
||||||
@ -182,15 +176,29 @@ class PhotoInfoActivity : BaseActivity<ActivityPhotoInfoBinding>() {
|
|||||||
layoutSize.isVisible = true
|
layoutSize.isVisible = true
|
||||||
layoutDate.isVisible = true
|
layoutDate.isVisible = true
|
||||||
|
|
||||||
layoutDuration.isVisible = false
|
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
|
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){
|
private fun loadImage(image: ImageView,file: File){
|
||||||
Glide.with(this@PhotoInfoActivity)
|
Glide.with(this@PhotoInfoActivity)
|
||||||
.load(file)
|
.load(file)
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
@ -14,6 +14,7 @@ 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.ActivityPhotoSortingBinding
|
import com.ux.video.file.filerecovery.databinding.ActivityPhotoSortingBinding
|
||||||
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
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.KEY_SCAN_TYPE
|
||||||
@ -97,21 +98,21 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
private var filterLayoutPopupWindows: FilterPopupWindows? = null
|
private var filterLayoutPopupWindows: FilterPopupWindows? = null
|
||||||
|
|
||||||
|
|
||||||
private lateinit var sortBySizeBigToSmall: List<ResultPhotosFiles>
|
private lateinit var sortBySizeBigToSmall: List<ResultDataFiles>
|
||||||
private lateinit var sortBySizeSmallToBig: List<ResultPhotosFiles>
|
private lateinit var sortBySizeSmallToBig: List<ResultDataFiles>
|
||||||
private lateinit var sortByDateReverse: List<Pair<String, List<ResultPhotosFiles>>>
|
private lateinit var sortByDateReverse: List<Pair<String, List<ResultDataFiles>>>
|
||||||
private lateinit var sortedByDatePositive: List<Pair<String, List<ResultPhotosFiles>>>
|
private lateinit var sortedByDatePositive: List<Pair<String, List<ResultDataFiles>>>
|
||||||
|
|
||||||
//最新显示的数据集合(包含缩略图 ,只保存当前筛选后或者排序后显示的数据,不受switch切换影响)
|
//最新显示的数据集合(包含缩略图 ,只保存当前筛选后或者排序后显示的数据,不受switch切换影响)
|
||||||
private var currentDateList: List<Pair<String, List<ResultPhotosFiles>>>? = null
|
private var currentDateList: List<Pair<String, List<ResultDataFiles>>>? = null
|
||||||
private var currentSizeList: List<ResultPhotosFiles>? = null
|
private var currentSizeList: List<ResultDataFiles>? = null
|
||||||
|
|
||||||
|
|
||||||
//选中的所有数据集合(实际选中)
|
//选中的所有数据集合(实际选中)
|
||||||
private lateinit var allSelectedSetList: Set<ResultPhotosFiles>
|
private lateinit var allSelectedSetList: Set<ResultDataFiles>
|
||||||
|
|
||||||
//选中的所有数据集合(筛选后的数据实际显示的所有选中)
|
//选中的所有数据集合(筛选后的数据实际显示的所有选中)
|
||||||
private lateinit var filterSelectedSetList: Set<ResultPhotosFiles>
|
private lateinit var filterSelectedSetList: Set<ResultDataFiles>
|
||||||
|
|
||||||
private lateinit var mItemDecoration: GridSpacingItemDecoration
|
private lateinit var mItemDecoration: GridSpacingItemDecoration
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
scanType = intent.getIntExtra(KEY_SCAN_TYPE, VALUE_SCAN_TYPE_photo)
|
||||||
val list: ArrayList<ResultPhotosFiles>? =
|
val list: ArrayList<ResultDataFiles>? =
|
||||||
intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE)
|
intent.getParcelableArrayListExtraCompat(KEY_PHOTO_FOLDER_FILE)
|
||||||
mItemDecoration =
|
mItemDecoration =
|
||||||
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
|
GridSpacingItemDecoration(columns, Common.itemSpacing, Common.horizontalSpacing)
|
||||||
@ -338,7 +339,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
is PhotoDisplayDateAdapter -> {
|
is PhotoDisplayDateAdapter -> {
|
||||||
dateAdapter?.setAllSelected(it.isSelected)
|
dateAdapter?.setAllSelected(it.isSelected)
|
||||||
dateAdapter?.getCurrentData()?.let {
|
dateAdapter?.getCurrentData()?.let {
|
||||||
it as List<Pair<String, List<ResultPhotosFiles>>>
|
it as List<Pair<String, List<ResultDataFiles>>>
|
||||||
if (it.size > 0)
|
if (it.size > 0)
|
||||||
Common.showLog("------------全选按钮 日期-${it.size} ${it[0].second[0].path}")
|
Common.showLog("------------全选按钮 日期-${it.size} ${it[0].second[0].path}")
|
||||||
}
|
}
|
||||||
@ -348,7 +349,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
is PhotoDisplayDateChildAdapter -> {
|
is PhotoDisplayDateChildAdapter -> {
|
||||||
sizeSortAdapter?.setAllSelected(it.isSelected)
|
sizeSortAdapter?.setAllSelected(it.isSelected)
|
||||||
sizeSortAdapter?.getCurrentData()?.let {
|
sizeSortAdapter?.getCurrentData()?.let {
|
||||||
it as List<ResultPhotosFiles>
|
it as List<ResultDataFiles>
|
||||||
if (it.size > 0)
|
if (it.size > 0)
|
||||||
Common.showLog("------------全选按钮 大小-${it.size} ${it[0].path}")
|
Common.showLog("------------全选按钮 大小-${it.size} ${it[0].path}")
|
||||||
}
|
}
|
||||||
@ -437,12 +438,12 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initGetCurrentSizeList(): List<ResultPhotosFiles> {
|
private fun initGetCurrentSizeList(): List<ResultDataFiles> {
|
||||||
currentSizeList = currentSizeList ?: currentDateList?.flatMap { it.second }
|
currentSizeList = currentSizeList ?: currentDateList?.flatMap { it.second }
|
||||||
return currentSizeList!!
|
return currentSizeList!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetCurrentSizeList(currentList: List<ResultPhotosFiles>) {
|
private fun resetCurrentSizeList(currentList: List<ResultDataFiles>) {
|
||||||
currentSizeList = currentList
|
currentSizeList = currentList
|
||||||
currentDateList = null
|
currentDateList = null
|
||||||
|
|
||||||
@ -451,12 +452,12 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initGetCurrentDateList(): List<Pair<String, List<ResultPhotosFiles>>> {
|
private fun initGetCurrentDateList(): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
currentDateList = currentDateList ?: Common.getSortByDayNewToOldInit(currentSizeList!!)
|
currentDateList = currentDateList ?: Common.getSortByDayNewToOldInit(currentSizeList!!)
|
||||||
return currentDateList!!
|
return currentDateList!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetCurrentDateList(currentList: List<Pair<String, List<ResultPhotosFiles>>>) {
|
private fun resetCurrentDateList(currentList: List<Pair<String, List<ResultDataFiles>>>) {
|
||||||
currentDateList = currentList
|
currentDateList = currentList
|
||||||
currentSizeList = null
|
currentSizeList = null
|
||||||
val totalSelectedCount = currentList.sumOf { pair ->
|
val totalSelectedCount = currentList.sumOf { pair ->
|
||||||
@ -484,7 +485,7 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
val aPx = 16.dpToPx(context)
|
val aPx = 16.dpToPx(context)
|
||||||
val bottom = 70.dpToPx(context)
|
val bottom = 70.dpToPx(context)
|
||||||
when (scanType) {
|
when (scanType) {
|
||||||
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio -> {
|
VALUE_SCAN_TYPE_audio, VALUE_SCAN_TYPE_deleted_audio,VALUE_SCAN_TYPE_documents, VALUE_SCAN_TYPE_deleted_documents -> {
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
setPadding(aPx, 0, 0, bottom)
|
setPadding(aPx, 0, 0, bottom)
|
||||||
}
|
}
|
||||||
@ -713,8 +714,8 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
* 数据筛选或者缩略图切换显示后,对比刷新实际显示的选中数据
|
* 数据筛选或者缩略图切换显示后,对比刷新实际显示的选中数据
|
||||||
*/
|
*/
|
||||||
private fun checkRefreshDisPlaySelected(
|
private fun checkRefreshDisPlaySelected(
|
||||||
list1: List<Pair<String, List<ResultPhotosFiles>>>? = null,
|
list1: List<Pair<String, List<ResultDataFiles>>>? = null,
|
||||||
list2: List<ResultPhotosFiles>? = null
|
list2: List<ResultDataFiles>? = null
|
||||||
) {
|
) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
list1?.let {
|
list1?.let {
|
||||||
@ -887,13 +888,13 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
//选中集合的更新
|
//选中集合的更新
|
||||||
viewModel.afterDeleted()
|
viewModel.afterDeleted()
|
||||||
deferredResults["sizeList"]?.let { list ->
|
deferredResults["sizeList"]?.let { list ->
|
||||||
list as List<ResultPhotosFiles>
|
list as List<ResultDataFiles>
|
||||||
Common.showLog("---------更新 sizeList = ${list.size}")
|
Common.showLog("---------更新 sizeList = ${list.size}")
|
||||||
sizeSortAdapter?.setData(list)
|
sizeSortAdapter?.setData(list)
|
||||||
resetCurrentSizeList(list)
|
resetCurrentSizeList(list)
|
||||||
}
|
}
|
||||||
deferredResults["dateList"]?.let { list ->
|
deferredResults["dateList"]?.let { list ->
|
||||||
list as List<Pair<String, List<ResultPhotosFiles>>>
|
list as List<Pair<String, List<ResultDataFiles>>>
|
||||||
Common.showLog("---------更新 dateList = ${list.size}")
|
Common.showLog("---------更新 dateList = ${list.size}")
|
||||||
dateAdapter?.setData(list)
|
dateAdapter?.setData(list)
|
||||||
resetCurrentDateList(list)
|
resetCurrentDateList(list)
|
||||||
@ -932,13 +933,13 @@ class PhotoSortingActivity : BaseActivity<ActivityPhotoSortingBinding>() {
|
|||||||
//选中集合的更新
|
//选中集合的更新
|
||||||
viewModel.afterSingleDeleted(deletedData)
|
viewModel.afterSingleDeleted(deletedData)
|
||||||
deferredResults["sizeList"]?.let { list ->
|
deferredResults["sizeList"]?.let { list ->
|
||||||
list as List<ResultPhotosFiles>
|
list as List<ResultDataFiles>
|
||||||
Common.showLog("---------更新 sizeList = ${list.size}")
|
Common.showLog("---------更新 sizeList = ${list.size}")
|
||||||
sizeSortAdapter?.setData(list)
|
sizeSortAdapter?.setData(list)
|
||||||
resetCurrentSizeList(list)
|
resetCurrentSizeList(list)
|
||||||
}
|
}
|
||||||
deferredResults["dateList"]?.let { list ->
|
deferredResults["dateList"]?.let { list ->
|
||||||
list as List<Pair<String, List<ResultPhotosFiles>>>
|
list as List<Pair<String, List<ResultDataFiles>>>
|
||||||
Common.showLog("---------更新 dateList = ${list.size}")
|
Common.showLog("---------更新 dateList = ${list.size}")
|
||||||
dateAdapter?.setData(list)
|
dateAdapter?.setData(list)
|
||||||
resetCurrentDateList(list)
|
resetCurrentDateList(list)
|
||||||
@ -1,9 +1,9 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import com.ux.video.file.filerecovery.db.ObjectBoxManager
|
||||||
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common
|
import com.ux.video.file.filerecovery.utils.Common
|
||||||
import com.ux.video.file.filerecovery.utils.ScanManager
|
import com.ux.video.file.filerecovery.utils.ScanManager
|
||||||
import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync
|
import com.ux.video.file.filerecovery.utils.ScanManager.copySelectedFilesAsync
|
||||||
@ -18,9 +18,9 @@ object RecoverOrDeleteManager {
|
|||||||
private var dialogConfirmDelete: ConfirmDeleteDialogFragment? = null
|
private var dialogConfirmDelete: ConfirmDeleteDialogFragment? = null
|
||||||
|
|
||||||
//详情页面进行删除操作的监听
|
//详情页面进行删除操作的监听
|
||||||
private var onSingleDeletedCompleteListener: ((ResultPhotosFiles) -> Unit)? = null
|
private var onSingleDeletedCompleteListener: ((ResultDataFiles) -> Unit)? = null
|
||||||
|
|
||||||
fun setOnSingleDeleteCompleteListener(listener: (ResultPhotosFiles) -> Unit) {
|
fun setOnSingleDeleteCompleteListener(listener: (ResultDataFiles) -> Unit) {
|
||||||
onSingleDeletedCompleteListener = listener
|
onSingleDeletedCompleteListener = listener
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,21 +31,10 @@ object RecoverOrDeleteManager {
|
|||||||
fun showRecoveringDialog(
|
fun showRecoveringDialog(
|
||||||
fragmentManager: FragmentManager,
|
fragmentManager: FragmentManager,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
selectedSetList: Set<ResultPhotosFiles>,
|
selectedSetList: Set<ResultDataFiles>,
|
||||||
onComplete: (number: Int) -> Unit
|
onComplete: (number: Int) -> Unit
|
||||||
) {
|
) {
|
||||||
scope.copySelectedFilesAsync(
|
|
||||||
selectedSet = selectedSetList,
|
|
||||||
folder = Common.recoveryPhotoDir,
|
|
||||||
onProgress = { currentCounts: Int, fileName: String, success: Boolean ->
|
|
||||||
ScanManager.showLog("--------恢复图片 ", "----------${currentCounts} ${fileName}")
|
|
||||||
dialogRecovering?.updateProgress(currentCounts)
|
|
||||||
|
|
||||||
}) { counts ->
|
|
||||||
dialogRecovering?.updateProgress(counts)
|
|
||||||
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
|
|
||||||
|
|
||||||
}
|
|
||||||
dialogRecovering = dialogRecovering ?: RecoveringDialogFragment()
|
dialogRecovering = dialogRecovering ?: RecoveringDialogFragment()
|
||||||
dialogRecovering?.run {
|
dialogRecovering?.run {
|
||||||
total = selectedSetList.size
|
total = selectedSetList.size
|
||||||
@ -55,6 +44,21 @@ object RecoverOrDeleteManager {
|
|||||||
}
|
}
|
||||||
show(fragmentManager, "")
|
show(fragmentManager, "")
|
||||||
}
|
}
|
||||||
|
scope.copySelectedFilesAsync(
|
||||||
|
selectedSet = selectedSetList,
|
||||||
|
folder = Common.recoveryPhotoDir,
|
||||||
|
onProgress = { currentCounts: Int, data: ResultDataFiles, fileName: String, success: Boolean ->
|
||||||
|
if(success){
|
||||||
|
ScanManager.showLog("--------恢复图片 ", "----------${currentCounts} ${fileName}")
|
||||||
|
dialogRecovering?.updateProgress(currentCounts)
|
||||||
|
ObjectBoxManager.addRecoveryFile(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
}) { counts ->
|
||||||
|
dialogRecovering?.updateProgress(counts)
|
||||||
|
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +68,7 @@ object RecoverOrDeleteManager {
|
|||||||
isInfoDelete: Boolean = false,
|
isInfoDelete: Boolean = false,
|
||||||
fragmentManager: FragmentManager,
|
fragmentManager: FragmentManager,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
selectedSetList: Set<ResultPhotosFiles>,
|
selectedSetList: Set<ResultDataFiles>,
|
||||||
onComplete: (number: Int) -> Unit
|
onComplete: (number: Int) -> Unit
|
||||||
) {
|
) {
|
||||||
dialogConfirmDelete = dialogConfirmDelete ?: ConfirmDeleteDialogFragment()
|
dialogConfirmDelete = dialogConfirmDelete ?: ConfirmDeleteDialogFragment()
|
||||||
@ -86,18 +90,10 @@ object RecoverOrDeleteManager {
|
|||||||
isInfoDelete: Boolean = false,
|
isInfoDelete: Boolean = false,
|
||||||
fragmentManager: FragmentManager,
|
fragmentManager: FragmentManager,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
selectedSetList: Set<ResultPhotosFiles>,
|
selectedSetList: Set<ResultDataFiles>,
|
||||||
onComplete: (number: Int) -> Unit
|
onComplete: (number: Int) -> Unit
|
||||||
) {
|
) {
|
||||||
scope.deleteFilesAsync(
|
|
||||||
selectedSet = selectedSetList,
|
|
||||||
onProgress = { currentCounts: Int, path: String, success: Boolean ->
|
|
||||||
ScanManager.showLog("--------删除图片 ", "----------${currentCounts} ${path}")
|
|
||||||
dialogDeleting?.updateProgress(currentCounts)
|
|
||||||
}) { counts ->
|
|
||||||
dialogDeleting?.updateProgress(counts)
|
|
||||||
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
|
|
||||||
}
|
|
||||||
dialogDeleting = dialogDeleting ?: DeletingDialogFragment()
|
dialogDeleting = dialogDeleting ?: DeletingDialogFragment()
|
||||||
dialogDeleting?.run {
|
dialogDeleting?.run {
|
||||||
total = selectedSetList.size
|
total = selectedSetList.size
|
||||||
@ -110,5 +106,18 @@ object RecoverOrDeleteManager {
|
|||||||
}
|
}
|
||||||
show(fragmentManager, "")
|
show(fragmentManager, "")
|
||||||
}
|
}
|
||||||
|
scope.deleteFilesAsync(
|
||||||
|
selectedSet = selectedSetList,
|
||||||
|
onProgress = { currentCounts: Int, data: ResultDataFiles, path: String, success: Boolean ->
|
||||||
|
if (success){
|
||||||
|
ScanManager.showLog("--------删除图片 ", "----------${currentCounts} ${path}")
|
||||||
|
dialogDeleting?.updateProgress(currentCounts)
|
||||||
|
ObjectBoxManager.deleteRecoveryFile(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
}) { counts ->
|
||||||
|
dialogDeleting?.updateProgress(counts)
|
||||||
|
ScanManager.showLog("--------恢复图片 ", "----------恢复完成 ${counts}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
|
import com.ux.video.file.filerecovery.base.BaseIngDialogFragment
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.ux.video.file.filerecovery.photo
|
package com.ux.video.file.filerecovery.sort
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -9,14 +9,13 @@ import android.os.Environment
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import com.ux.video.file.filerecovery.App
|
|
||||||
import com.ux.video.file.filerecovery.R
|
import com.ux.video.file.filerecovery.R
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.utils.ExtendFunctions.dpToPx
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.collections.sortedBy
|
import kotlin.collections.sortedBy
|
||||||
@ -40,24 +39,25 @@ object Common {
|
|||||||
val rootDir = Environment.getExternalStorageDirectory()
|
val rootDir = Environment.getExternalStorageDirectory()
|
||||||
val dateFormat = SimpleDateFormat("MMMM d,yyyy", Locale.ENGLISH)
|
val dateFormat = SimpleDateFormat("MMMM d,yyyy", Locale.ENGLISH)
|
||||||
val chineseFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINESE)
|
val chineseFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINESE)
|
||||||
|
val itemDateFormat = SimpleDateFormat("MM-dd", Locale.CHINESE)
|
||||||
val recoveryPhotoDir = "MyAllRecovery/Photo"
|
val recoveryPhotoDir = "MyAllRecovery/Photo"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认按照日期分类,将最新的排前面 降序
|
* 默认按照日期分类,将最新的排前面 降序
|
||||||
*/
|
*/
|
||||||
fun getSortByDayNewToOldInit(list: List<ResultPhotosFiles>): List<Pair<String, List<ResultPhotosFiles>>> {
|
fun getSortByDayNewToOldInit(list: List<ResultDataFiles>): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
val grouped = list.groupBy {
|
val grouped = list.groupBy {
|
||||||
dateFormat.format(Date(it.lastModified))
|
dateFormat.format(Date(it.lastModified))
|
||||||
}
|
}
|
||||||
val parentData: List<Pair<String, List<ResultPhotosFiles>>> = grouped
|
val parentData: List<Pair<String, List<ResultDataFiles>>> = grouped
|
||||||
.map { it.key to it.value }
|
.map { it.key to it.value }
|
||||||
.sortedByDescending { dateFormat.parse(it.first)?.time ?: 0L }
|
.sortedByDescending { dateFormat.parse(it.first)?.time ?: 0L }
|
||||||
return parentData
|
return parentData
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSortByDayNewToOld(
|
fun getSortByDayNewToOld(
|
||||||
list: List<Pair<String, List<ResultPhotosFiles>>>
|
list: List<Pair<String, List<ResultDataFiles>>>
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
return list.sortedByDescending { pair ->
|
return list.sortedByDescending { pair ->
|
||||||
dateFormat.parse(pair.first)?.time ?: 0L
|
dateFormat.parse(pair.first)?.time ?: 0L
|
||||||
}
|
}
|
||||||
@ -68,28 +68,28 @@ object Common {
|
|||||||
* 按照日期排序, 时间最早的排前面 升序
|
* 按照日期排序, 时间最早的排前面 升序
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
fun getSortByDayOldToNew(list: List<Pair<String, List<ResultPhotosFiles>>>) =
|
fun getSortByDayOldToNew(list: List<Pair<String, List<ResultDataFiles>>>) =
|
||||||
list.sortedBy { dateFormat.parse(it.first)?.time ?: 0L }
|
list.sortedBy { dateFormat.parse(it.first)?.time ?: 0L }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照文件大小排序,将最大的排前面 降序
|
* 按照文件大小排序,将最大的排前面 降序
|
||||||
*/
|
*/
|
||||||
fun getSortBySizeBigToSmall(list: List<ResultPhotosFiles>) = list.sortedByDescending {
|
fun getSortBySizeBigToSmall(list: List<ResultDataFiles>) = list.sortedByDescending {
|
||||||
it.size
|
it.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照文件大小排序,将最小的排前面 升序
|
* 按照文件大小排序,将最小的排前面 升序
|
||||||
*/
|
*/
|
||||||
fun getSortBySizeSmallToBig(list: List<ResultPhotosFiles>) = list.sortedBy {
|
fun getSortBySizeSmallToBig(list: List<ResultDataFiles>) = list.sortedBy {
|
||||||
it.size
|
it.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun searchByName(
|
fun searchByName(
|
||||||
data: List<Pair<String, List<ResultPhotosFiles>>>,
|
data: List<Pair<String, List<ResultDataFiles>>>,
|
||||||
keyword: String
|
keyword: String
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
if (keyword.isBlank()) return data
|
if (keyword.isBlank()) return data
|
||||||
|
|
||||||
return data.mapNotNull { (key, files) ->
|
return data.mapNotNull { (key, files) ->
|
||||||
@ -98,9 +98,9 @@ object Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun searchByNameList(
|
fun searchByNameList(
|
||||||
list: List<ResultPhotosFiles>,
|
list: List<ResultDataFiles>,
|
||||||
keyword: String
|
keyword: String
|
||||||
): List<ResultPhotosFiles> {
|
): List<ResultDataFiles> {
|
||||||
if (keyword.isBlank()) return list
|
if (keyword.isBlank()) return list
|
||||||
return list.filter { it.name.contains(keyword, ignoreCase = true) }
|
return list.filter { it.name.contains(keyword, ignoreCase = true) }
|
||||||
}
|
}
|
||||||
@ -135,8 +135,8 @@ object Common {
|
|||||||
* @param months 筛选months月之内的数据
|
* @param months 筛选months月之内的数据
|
||||||
*/
|
*/
|
||||||
fun filterWithinOneMonthByDay(
|
fun filterWithinOneMonthByDay(
|
||||||
grouped: List<Pair<String, List<ResultPhotosFiles>>>, months: Int
|
grouped: List<Pair<String, List<ResultDataFiles>>>, months: Int
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
val today = Calendar.getInstance()
|
val today = Calendar.getInstance()
|
||||||
val oneMonthAgo = Calendar.getInstance().apply {
|
val oneMonthAgo = Calendar.getInstance().apply {
|
||||||
add(Calendar.MONTH, -months) // 1 个月前
|
add(Calendar.MONTH, -months) // 1 个月前
|
||||||
@ -151,7 +151,7 @@ object Common {
|
|||||||
/**
|
/**
|
||||||
* @param months 筛选months月之内的数据
|
* @param months 筛选months月之内的数据
|
||||||
*/
|
*/
|
||||||
fun filterWithinOneMonth(list: List<ResultPhotosFiles>, months: Int): List<ResultPhotosFiles> {
|
fun filterWithinOneMonth(list: List<ResultDataFiles>, months: Int): List<ResultDataFiles> {
|
||||||
val today = Calendar.getInstance()
|
val today = Calendar.getInstance()
|
||||||
val oneMonthAgo = Calendar.getInstance().apply {
|
val oneMonthAgo = Calendar.getInstance().apply {
|
||||||
add(Calendar.MONTH, -months)
|
add(Calendar.MONTH, -months)
|
||||||
@ -184,10 +184,10 @@ object Common {
|
|||||||
* @return 显示的选中数量和选中集合
|
* @return 显示的选中数量和选中集合
|
||||||
*/
|
*/
|
||||||
fun checkSelectListContainDate(
|
fun checkSelectListContainDate(
|
||||||
list: List<Pair<String, List<ResultPhotosFiles>>>,
|
list: List<Pair<String, List<ResultDataFiles>>>,
|
||||||
selected: Set<ResultPhotosFiles>
|
selected: Set<ResultDataFiles>
|
||||||
): Pair<Int, MutableSet<ResultPhotosFiles>> {
|
): Pair<Int, MutableSet<ResultDataFiles>> {
|
||||||
val currentSelected = mutableSetOf<ResultPhotosFiles>()
|
val currentSelected = mutableSetOf<ResultDataFiles>()
|
||||||
|
|
||||||
val totalSelectedCount = list.sumOf { pair ->
|
val totalSelectedCount = list.sumOf { pair ->
|
||||||
pair.second.count {
|
pair.second.count {
|
||||||
@ -202,10 +202,10 @@ object Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkSelectListContainDateAsync(
|
suspend fun checkSelectListContainDateAsync(
|
||||||
list: List<Pair<String, List<ResultPhotosFiles>>>,
|
list: List<Pair<String, List<ResultDataFiles>>>,
|
||||||
selected: Set<ResultPhotosFiles>
|
selected: Set<ResultDataFiles>
|
||||||
): Pair<Int, MutableSet<ResultPhotosFiles>> = withContext(Dispatchers.Default) {
|
): Pair<Int, MutableSet<ResultDataFiles>> = withContext(Dispatchers.Default) {
|
||||||
val currentSelected = mutableSetOf<ResultPhotosFiles>()
|
val currentSelected = mutableSetOf<ResultDataFiles>()
|
||||||
var totalSelectedCount = 0
|
var totalSelectedCount = 0
|
||||||
|
|
||||||
// 高效遍历外层 + 内层列表
|
// 高效遍历外层 + 内层列表
|
||||||
@ -238,10 +238,10 @@ object Common {
|
|||||||
|
|
||||||
|
|
||||||
suspend fun checkSelectListContainSize(
|
suspend fun checkSelectListContainSize(
|
||||||
list: List<ResultPhotosFiles>,
|
list: List<ResultDataFiles>,
|
||||||
selected: Set<ResultPhotosFiles>
|
selected: Set<ResultDataFiles>
|
||||||
): Pair<Int, MutableSet<ResultPhotosFiles>> = withContext(Dispatchers.Default) {
|
): Pair<Int, MutableSet<ResultDataFiles>> = withContext(Dispatchers.Default) {
|
||||||
val currentSelected = mutableSetOf<ResultPhotosFiles>()
|
val currentSelected = mutableSetOf<ResultDataFiles>()
|
||||||
var totalSelectedCount = 0
|
var totalSelectedCount = 0
|
||||||
|
|
||||||
// 高效遍历外层 + 内层列表
|
// 高效遍历外层 + 内层列表
|
||||||
@ -259,8 +259,8 @@ object Common {
|
|||||||
* 去掉缩略图的集合
|
* 去掉缩略图的集合
|
||||||
*/
|
*/
|
||||||
suspend fun filterThumbnailsAsync(
|
suspend fun filterThumbnailsAsync(
|
||||||
originalList: MutableList<Pair<String, List<ResultPhotosFiles>>>
|
originalList: MutableList<Pair<String, List<ResultDataFiles>>>
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> = withContext(Dispatchers.Default) {
|
): List<Pair<String, List<ResultDataFiles>>> = withContext(Dispatchers.Default) {
|
||||||
originalList.asSequence()
|
originalList.asSequence()
|
||||||
.map { (key, files) ->
|
.map { (key, files) ->
|
||||||
key to files.asSequence().filter { !it.isThumbnail }.toList()
|
key to files.asSequence().filter { !it.isThumbnail }.toList()
|
||||||
@ -271,9 +271,9 @@ object Common {
|
|||||||
|
|
||||||
|
|
||||||
fun removeSelectedFromList(
|
fun removeSelectedFromList(
|
||||||
list: List<Pair<String, List<ResultPhotosFiles>>>,
|
list: List<Pair<String, List<ResultDataFiles>>>,
|
||||||
selectedLiveData: Set<ResultPhotosFiles>
|
selectedLiveData: Set<ResultDataFiles>
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
return list.mapNotNull { (key, files) ->
|
return list.mapNotNull { (key, files) ->
|
||||||
val filtered = files.filterNot { it in selectedLiveData }
|
val filtered = files.filterNot { it in selectedLiveData }
|
||||||
if (filtered.isNotEmpty()) key to filtered else null
|
if (filtered.isNotEmpty()) key to filtered else null
|
||||||
@ -281,9 +281,9 @@ object Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeSelectedFromSizeList(
|
fun removeSelectedFromSizeList(
|
||||||
list: List<ResultPhotosFiles>,
|
list: List<ResultDataFiles>,
|
||||||
selectedLiveData: Set<ResultPhotosFiles>
|
selectedLiveData: Set<ResultDataFiles>
|
||||||
): List<ResultPhotosFiles> {
|
): List<ResultDataFiles> {
|
||||||
return list.filterNot { it in selectedLiveData }
|
return list.filterNot { it in selectedLiveData }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +304,7 @@ object Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
fun formatDuration(ms: Long): String {
|
fun formatDuration(ms: Long): String {
|
||||||
val totalSeconds = ms / 1000
|
val totalSeconds = ms / 1000
|
||||||
val hours = totalSeconds / 3600
|
val hours = totalSeconds / 3600
|
||||||
@ -316,11 +317,66 @@ object Common {
|
|||||||
String.format("%02d:%02d", minutes, seconds)
|
String.format("%02d:%02d", minutes, seconds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun getFileMIME(file: File): String {
|
||||||
|
val ext = file.extension.lowercase()
|
||||||
|
val mimeTypeFromExtension = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext)
|
||||||
|
|
||||||
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext) ?: return "unknown"
|
||||||
|
return mime
|
||||||
|
return when {
|
||||||
|
mime.startsWith("image/") -> "image"
|
||||||
|
mime.startsWith("video/") -> "video"
|
||||||
|
mime.startsWith("audio/") -> "audio"
|
||||||
|
mime.startsWith("text/") -> "document"
|
||||||
|
mime == "application/pdf" -> "document"
|
||||||
|
mime.startsWith("application/vnd.openxmlformats") -> "document"
|
||||||
|
mime.startsWith("application/ms") -> "document"
|
||||||
|
mime == "application/zip" ||
|
||||||
|
mime == "application/x-rar-compressed" ||
|
||||||
|
mime == "application/x-7z-compressed" -> "archive"
|
||||||
|
else -> "other"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val customMimeMap = mapOf(
|
||||||
|
"xapk" to "application/zip",
|
||||||
|
// 可以继续添加其他自定义扩展名
|
||||||
|
)
|
||||||
|
fun getMimeTypeParts(file: File): String {
|
||||||
|
val extension = file.extension.lowercase()
|
||||||
|
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)?:customMimeMap[extension]
|
||||||
|
showLog("-----------ext=$extension mimeType=${mimeType}")
|
||||||
|
return if (mimeType != null && mimeType.contains("/")) {
|
||||||
|
val parts = mimeType.split("/")
|
||||||
|
val mainType = parts[0]
|
||||||
|
val subType = parts.getOrNull(1)
|
||||||
|
"$mainType/$subType"
|
||||||
|
} else {
|
||||||
|
"unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFileIconRes(file: File): Int {
|
||||||
|
val ext = file.extension.lowercase()
|
||||||
|
|
||||||
|
return when (ext) {
|
||||||
|
"doc", "docx" -> R.drawable.icon_doc
|
||||||
|
"xls", "xlsx" -> R.drawable.icon_xls
|
||||||
|
"ppt", "pptx" -> R.drawable.icon_ppt
|
||||||
|
"pdf" -> R.drawable.icon_pdf
|
||||||
|
"txt" -> R.drawable.icon_txt
|
||||||
|
"apk", "xapk" -> R.drawable.icon_apk
|
||||||
|
else -> R.drawable.icon_unknow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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{
|
||||||
|
return itemDateFormat.format(time)
|
||||||
|
}
|
||||||
|
|
||||||
fun getChineseFormatDate(date: Date): String {
|
fun getChineseFormatDate(date: Date): String {
|
||||||
return chineseFormat.format(date)
|
return chineseFormat.format(date)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import android.os.Build
|
|||||||
import android.os.Parcelable
|
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.photo.ResultPhotosFiles
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -40,11 +40,11 @@ object ExtendFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun List<ResultPhotosFiles>.filterWithinDateRangeList(
|
fun List<ResultDataFiles>.filterWithinDateRangeList(
|
||||||
months: Int = -1,
|
months: Int = -1,
|
||||||
startDate: Date? = null,
|
startDate: Date? = null,
|
||||||
endDate: Date? = null
|
endDate: Date? = null
|
||||||
): List<ResultPhotosFiles> {
|
): List<ResultDataFiles> {
|
||||||
|
|
||||||
val today = Calendar.getInstance()
|
val today = Calendar.getInstance()
|
||||||
|
|
||||||
@ -79,11 +79,11 @@ object ExtendFunctions {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun List<Pair<String, List<ResultPhotosFiles>>>.filterWithinDateRange(
|
fun List<Pair<String, List<ResultDataFiles>>>.filterWithinDateRange(
|
||||||
months: Int = -1,
|
months: Int = -1,
|
||||||
startDate: Date? = null,
|
startDate: Date? = null,
|
||||||
endDate: Date? = null
|
endDate: Date? = null
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
|
|
||||||
val sdf = Common.dateFormat
|
val sdf = Common.dateFormat
|
||||||
val today = Calendar.getInstance()
|
val today = Calendar.getInstance()
|
||||||
@ -118,10 +118,10 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 按文件大小筛选:区间 [minSize, maxSize]
|
* 按文件大小筛选:区间 [minSize, maxSize]
|
||||||
*/
|
*/
|
||||||
fun List<ResultPhotosFiles>.filterBySizeList(
|
fun List<ResultDataFiles>.filterBySizeList(
|
||||||
minSize: Long,
|
minSize: Long,
|
||||||
maxSize: Long
|
maxSize: Long
|
||||||
): List<ResultPhotosFiles> {
|
): List<ResultDataFiles> {
|
||||||
if (minSize == -1L) return this
|
if (minSize == -1L) return this
|
||||||
return this.filter { it.size in minSize..maxSize }
|
return this.filter { it.size in minSize..maxSize }
|
||||||
}
|
}
|
||||||
@ -129,10 +129,10 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 按文件大小筛选:区间 [minSize, maxSize]
|
* 按文件大小筛选:区间 [minSize, maxSize]
|
||||||
*/
|
*/
|
||||||
fun List<ResultPhotosFiles>.filterByDurationList(
|
fun List<ResultDataFiles>.filterByDurationList(
|
||||||
minSize: Long,
|
minSize: Long,
|
||||||
maxSize: Long
|
maxSize: Long
|
||||||
): List<ResultPhotosFiles> {
|
): 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 }
|
||||||
}
|
}
|
||||||
@ -140,10 +140,10 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 分组数据:按大小筛选 ,图片和文件筛选文件大小
|
* 分组数据:按大小筛选 ,图片和文件筛选文件大小
|
||||||
*/
|
*/
|
||||||
fun List<Pair<String, List<ResultPhotosFiles>>>.filterBySize(
|
fun List<Pair<String, List<ResultDataFiles>>>.filterBySize(
|
||||||
minSize: Long,
|
minSize: Long,
|
||||||
maxSize: Long
|
maxSize: Long
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): 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.size in minSize..maxSize }
|
val filtered = files.filter { it.size in minSize..maxSize }
|
||||||
@ -154,10 +154,10 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 分组数据:按大小筛选 ,音视频筛选时长
|
* 分组数据:按大小筛选 ,音视频筛选时长
|
||||||
*/
|
*/
|
||||||
fun List<Pair<String, List<ResultPhotosFiles>>>.filterByDuration(
|
fun List<Pair<String, List<ResultDataFiles>>>.filterByDuration(
|
||||||
minSize: Long,
|
minSize: Long,
|
||||||
maxSize: Long
|
maxSize: Long
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): 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 }
|
||||||
@ -181,7 +181,7 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 移除掉缩略图后的数据
|
* 移除掉缩略图后的数据
|
||||||
*/
|
*/
|
||||||
suspend fun List<Pair<String, List<ResultPhotosFiles>>>.filterThumbnailsAsync(): List<Pair<String, List<ResultPhotosFiles>>> =
|
suspend fun List<Pair<String, List<ResultDataFiles>>>.filterThumbnailsAsync(): List<Pair<String, List<ResultDataFiles>>> =
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
this@filterThumbnailsAsync.asSequence()
|
this@filterThumbnailsAsync.asSequence()
|
||||||
.mapNotNull { (key, files) ->
|
.mapNotNull { (key, files) ->
|
||||||
@ -195,7 +195,7 @@ object ExtendFunctions {
|
|||||||
/**
|
/**
|
||||||
* 移除掉缩略图后的数据
|
* 移除掉缩略图后的数据
|
||||||
*/
|
*/
|
||||||
suspend fun List<ResultPhotosFiles>.filterRemoveThumbnailsAsync(): List<ResultPhotosFiles> =
|
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 的项
|
||||||
@ -203,9 +203,9 @@ object ExtendFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun List<Pair<String, List<ResultPhotosFiles>>>.removeItem(
|
fun List<Pair<String, List<ResultDataFiles>>>.removeItem(
|
||||||
target: ResultPhotosFiles
|
target: ResultDataFiles
|
||||||
): List<Pair<String, List<ResultPhotosFiles>>> {
|
): List<Pair<String, List<ResultDataFiles>>> {
|
||||||
return this.mapNotNull { (key, files) ->
|
return this.mapNotNull { (key, files) ->
|
||||||
val updatedFiles = files.filterNot { it == target }
|
val updatedFiles = files.filterNot { it == target }
|
||||||
if (updatedFiles.isNotEmpty()) key to updatedFiles else null
|
if (updatedFiles.isNotEmpty()) key to updatedFiles else null
|
||||||
|
|||||||
@ -5,14 +5,11 @@ 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.os.Build
|
|
||||||
import android.os.Environment
|
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
|
import android.text.format.Formatter
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
|
||||||
import com.ux.video.file.filerecovery.result.ScanningActivity
|
|
||||||
import com.ux.video.file.filerecovery.utils.Common.VALUE_SCAN_TYPE_audio
|
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_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_documents
|
||||||
@ -27,7 +24,6 @@ import kotlinx.coroutines.currentCoroutineContext
|
|||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -108,20 +104,21 @@ object ScanManager {
|
|||||||
|
|
||||||
scanDocuments(root, depth = 0)
|
scanDocuments(root, depth = 0)
|
||||||
val map = result.map { (dir, files) ->
|
val map = result.map { (dir, files) ->
|
||||||
val resultPhotosFilesList = files.map { file ->
|
val resultDataFilesList = files.map { file ->
|
||||||
ResultPhotosFiles(
|
ResultDataFiles(
|
||||||
name = file.name,
|
name = file.name,
|
||||||
path = file.absolutePath,
|
path = file.absolutePath,
|
||||||
size = file.length(),
|
size = file.length(),
|
||||||
sizeString = android.text.format.Formatter.formatFileSize(
|
sizeString = Formatter.formatFileSize(
|
||||||
context,
|
context,
|
||||||
file.length()
|
file.length()
|
||||||
),
|
),
|
||||||
lastModified = file.lastModified(),
|
lastModified = file.lastModified(),
|
||||||
resolution = getResolution(type,file)
|
resolution = getResolution(type,file),
|
||||||
|
fileType = getFileType(type)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ResultPhotos(dir, ArrayList(resultPhotosFilesList))
|
ResultData(dir, ArrayList(resultDataFilesList))
|
||||||
}
|
}
|
||||||
emit(ScanState.Complete(ArrayList(map)))
|
emit(ScanState.Complete(ArrayList(map)))
|
||||||
}
|
}
|
||||||
@ -168,7 +165,7 @@ object ScanManager {
|
|||||||
val result = mutableMapOf<String, MutableList<File>>()
|
val result = mutableMapOf<String, MutableList<File>>()
|
||||||
var fileCount = 0
|
var fileCount = 0
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
|
||||||
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
|
||||||
@ -211,28 +208,40 @@ object ScanManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
scanDir(root, depth = 0)
|
scanDir(root, depth = 0)
|
||||||
|
|
||||||
ScanManager.showLog("HiddenScan", " 3333")
|
ScanManager.showLog("HiddenScan", " 3333")
|
||||||
val map = result.map { (dir, files) ->
|
val map = result.map { (dir, files) ->
|
||||||
val resultPhotosFilesList = files.map { file ->
|
val resultDataFilesList = files.map { file ->
|
||||||
ResultPhotosFiles(
|
ResultDataFiles(
|
||||||
name = file.name,
|
name = file.name,
|
||||||
path = file.absolutePath,
|
path = file.absolutePath,
|
||||||
size = file.length(),
|
size = file.length(),
|
||||||
sizeString = android.text.format.Formatter.formatFileSize(
|
sizeString = Formatter.formatFileSize(
|
||||||
context,
|
context,
|
||||||
file.length()
|
file.length()
|
||||||
),
|
),
|
||||||
lastModified = file.lastModified(),
|
lastModified = file.lastModified(),
|
||||||
resolution = getResolution(type,file)
|
resolution = getResolution(type,file),
|
||||||
|
fileType = getFileType(type)
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
ResultPhotos(dir, ArrayList(resultPhotosFilesList))
|
ResultData(dir, ArrayList(resultDataFilesList))
|
||||||
}
|
}
|
||||||
emit(ScanState.Complete(ArrayList(map)))
|
emit(ScanState.Complete(ArrayList(map)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getFileType(scanType: Int): Int {
|
||||||
|
return when (scanType) {
|
||||||
|
VALUE_SCAN_TYPE_deleted_photo -> 0
|
||||||
|
|
||||||
|
VALUE_SCAN_TYPE_deleted_video -> 1
|
||||||
|
|
||||||
|
VALUE_SCAN_TYPE_deleted_audio -> 2
|
||||||
|
|
||||||
|
else -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
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)
|
||||||
context.contentResolver.query(uri, arrayOf(OpenableColumns.SIZE), null, null, null)
|
context.contentResolver.query(uri, arrayOf(OpenableColumns.SIZE), null, null, null)
|
||||||
@ -291,13 +300,14 @@ object ScanManager {
|
|||||||
* @param folder "AllRecovery/Photo"
|
* @param folder "AllRecovery/Photo"
|
||||||
*/
|
*/
|
||||||
fun CoroutineScope.copySelectedFilesAsync(
|
fun CoroutineScope.copySelectedFilesAsync(
|
||||||
selectedSet: Set<ResultPhotosFiles>,
|
selectedSet: Set<ResultDataFiles>,
|
||||||
rootDir: File = Common.rootDir,
|
rootDir: File = Common.rootDir,
|
||||||
folder: String,
|
folder: String,
|
||||||
onProgress: (currentCounts: Int, fileName: String, success: Boolean) -> Unit,
|
onProgress: (currentCounts: Int, data:ResultDataFiles,fileName: String, success: Boolean) -> Unit,
|
||||||
onComplete: (currentCounts: Int) -> Unit
|
onComplete: (currentCounts: Int) -> Unit
|
||||||
) {
|
) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
|
var recoveryCount = 0
|
||||||
val targetDir = File(rootDir, folder)
|
val targetDir = File(rootDir, folder)
|
||||||
if (!targetDir.exists()) targetDir.mkdirs()
|
if (!targetDir.exists()) targetDir.mkdirs()
|
||||||
selectedSet.forEachIndexed { index, resultPhotosFiles ->
|
selectedSet.forEachIndexed { index, resultPhotosFiles ->
|
||||||
@ -312,17 +322,19 @@ object ScanManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
success = true
|
success = true
|
||||||
|
recoveryCount++
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
onProgress(index + 1,resultPhotosFiles, srcFile.name, success)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
onProgress(index + 1, srcFile.name, success)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
onComplete(selectedSet.size)
|
onComplete(recoveryCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,8 +345,8 @@ object ScanManager {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
fun CoroutineScope.deleteFilesAsync(
|
fun CoroutineScope.deleteFilesAsync(
|
||||||
selectedSet: Set<ResultPhotosFiles>,
|
selectedSet: Set<ResultDataFiles>,
|
||||||
onProgress: (currentCounts: Int, fileName: String, success: Boolean) -> Unit,
|
onProgress: (currentCounts: Int, data:ResultDataFiles,fileName: String, success: Boolean) -> Unit,
|
||||||
onComplete: (currentCounts: Int) -> Unit
|
onComplete: (currentCounts: Int) -> Unit
|
||||||
) {
|
) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
@ -346,16 +358,20 @@ object ScanManager {
|
|||||||
deletedCount++
|
deletedCount++
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
onProgress(index + 1, file.name, true)
|
onProgress(index + 1, resultPhotosFiles,file.name, true)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
onProgress(index + 1, resultPhotosFiles.path!!, false)
|
onProgress(index + 1,resultPhotosFiles, resultPhotosFiles.path!!, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
onComplete(selectedSet.size)
|
onComplete(deletedCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
package com.ux.video.file.filerecovery.utils
|
package com.ux.video.file.filerecovery.utils
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
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.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
|
|
||||||
|
|
||||||
class ScanRepository : ViewModel() {
|
class ScanRepository : ViewModel() {
|
||||||
@ -20,17 +16,17 @@ class ScanRepository : ViewModel() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private val _selectedLiveData = MutableLiveData<Set<ResultPhotosFiles>>(emptySet())
|
private val _selectedLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
val selectedLiveData: LiveData<Set<ResultPhotosFiles>> = _selectedLiveData
|
val selectedLiveData: LiveData<Set<ResultDataFiles>> = _selectedLiveData
|
||||||
|
|
||||||
// 当前筛选显示的选中项
|
// 当前筛选显示的选中项
|
||||||
private val _selectedDisplayLiveData = MutableLiveData<Set<ResultPhotosFiles>>(emptySet())
|
private val _selectedDisplayLiveData = MutableLiveData<Set<ResultDataFiles>>(emptySet())
|
||||||
val selectedDisplayLiveData: LiveData<Set<ResultPhotosFiles>> = _selectedDisplayLiveData
|
val selectedDisplayLiveData: LiveData<Set<ResultDataFiles>> = _selectedDisplayLiveData
|
||||||
|
|
||||||
fun toggleSelection(isAdd: Boolean, resultPhotosFiles: ResultPhotosFiles) {
|
fun toggleSelection(isAdd: Boolean, resultDataFiles: ResultDataFiles) {
|
||||||
val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
|
val current = _selectedLiveData.value?.toMutableSet() ?: mutableSetOf()
|
||||||
val currentDisplay = _selectedDisplayLiveData.value?.toMutableSet() ?: mutableSetOf()
|
val currentDisplay = _selectedDisplayLiveData.value?.toMutableSet() ?: mutableSetOf()
|
||||||
resultPhotosFiles.let {
|
resultDataFiles.let {
|
||||||
if (isAdd) {
|
if (isAdd) {
|
||||||
current.add(it)
|
current.add(it)
|
||||||
currentDisplay.add(it)
|
currentDisplay.add(it)
|
||||||
@ -52,7 +48,7 @@ class ScanRepository : ViewModel() {
|
|||||||
/**
|
/**
|
||||||
* 数据筛选后或者缩略图显示开关切换后 重置当前显示的选中集合
|
* 数据筛选后或者缩略图显示开关切换后 重置当前显示的选中集合
|
||||||
*/
|
*/
|
||||||
fun filterResetDisplayFlow(list: MutableSet<ResultPhotosFiles>){
|
fun filterResetDisplayFlow(list: MutableSet<ResultDataFiles>){
|
||||||
_selectedDisplayLiveData.value = list.toSet()
|
_selectedDisplayLiveData.value = list.toSet()
|
||||||
|
|
||||||
Common.showLog( "筛选后重置 _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ")
|
Common.showLog( "筛选后重置 _selectedDisplayFlow=${_selectedDisplayLiveData.value?.size} _selectedFlow=${_selectedLiveData.value?.size} ")
|
||||||
@ -75,7 +71,7 @@ class ScanRepository : ViewModel() {
|
|||||||
/**
|
/**
|
||||||
* 详情页删除完毕,移除删除掉的数据
|
* 详情页删除完毕,移除删除掉的数据
|
||||||
*/
|
*/
|
||||||
fun afterSingleDeleted(deletedItem:ResultPhotosFiles){
|
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()
|
||||||
|
|
||||||
@ -88,9 +84,9 @@ class ScanRepository : ViewModel() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun checkIsSelect(resultPhotosFiles: ResultPhotosFiles): Boolean {
|
fun checkIsSelect(resultDataFiles: ResultDataFiles): Boolean {
|
||||||
val current = _selectedLiveData.value
|
val current = _selectedLiveData.value
|
||||||
return current?.contains(resultPhotosFiles) == true
|
return current?.contains(resultDataFiles) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package com.ux.video.file.filerecovery.utils
|
package com.ux.video.file.filerecovery.utils
|
||||||
|
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotos
|
import com.ux.video.file.filerecovery.db.ResultData
|
||||||
|
|
||||||
|
|
||||||
sealed class ScanState {
|
sealed class ScanState {
|
||||||
data class Progress(val scannedCount: Int,val filePath: String) : ScanState()
|
data class Progress(val scannedCount: Int,val filePath: String) : ScanState()
|
||||||
data class Complete(val result: ArrayList<ResultPhotos>) : ScanState()
|
data class Complete(val result: ArrayList<ResultData>) : ScanState()
|
||||||
}
|
}
|
||||||
@ -3,27 +3,18 @@ package com.ux.video.file.filerecovery.video
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.SeekBar
|
|
||||||
import androidx.activity.enableEdgeToEdge
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
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.ActivityScanSelectTypeBinding
|
|
||||||
import com.ux.video.file.filerecovery.databinding.ActivityVideoPlayBinding
|
import com.ux.video.file.filerecovery.databinding.ActivityVideoPlayBinding
|
||||||
import com.ux.video.file.filerecovery.photo.PhotoInfoActivity
|
import com.ux.video.file.filerecovery.sort.RecoverOrDeleteManager
|
||||||
import com.ux.video.file.filerecovery.photo.PhotoInfoActivity.Companion.KEY_CLICK_ITEM
|
import com.ux.video.file.filerecovery.db.ResultDataFiles
|
||||||
import com.ux.video.file.filerecovery.photo.RecoverOrDeleteManager
|
|
||||||
import com.ux.video.file.filerecovery.photo.ResultPhotosFiles
|
|
||||||
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
|
||||||
|
|
||||||
@ -34,7 +25,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var player: ExoPlayer
|
private lateinit var player: ExoPlayer
|
||||||
private var myData: ResultPhotosFiles? = null
|
private var myData: ResultDataFiles? = null
|
||||||
private val updateHandler = Handler(Looper.getMainLooper())
|
private val updateHandler = Handler(Looper.getMainLooper())
|
||||||
override fun inflateBinding(inflater: LayoutInflater): ActivityVideoPlayBinding =
|
override fun inflateBinding(inflater: LayoutInflater): ActivityVideoPlayBinding =
|
||||||
ActivityVideoPlayBinding.inflate(inflater)
|
ActivityVideoPlayBinding.inflate(inflater)
|
||||||
@ -48,7 +39,7 @@ class VideoPlayActivity : BaseActivity<ActivityVideoPlayBinding>() {
|
|||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
myData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
intent.getParcelableExtra(KEY_DATA, ResultPhotosFiles::class.java)
|
intent.getParcelableExtra(KEY_DATA, ResultDataFiles::class.java)
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
intent.getParcelableExtra(KEY_DATA)
|
intent.getParcelableExtra(KEY_DATA)
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/main_title" android:state_selected="true"/>
|
||||||
|
<item android:color="@color/main_sub_title" android:state_selected="false"/>
|
||||||
|
|
||||||
|
</selector>
|
||||||
BIN
app/src/main/res/drawable/icon_apk.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/drawable/icon_doc.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/src/main/res/drawable/icon_pdf.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
app/src/main/res/drawable/icon_ppt.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
app/src/main/res/drawable/icon_txt.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
app/src/main/res/drawable/icon_unknow.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
app/src/main/res/drawable/icon_xls.png
Normal file
|
After Width: | Height: | Size: 26 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=".photo.PhotoInfoActivity">
|
tools:context=".sort.PhotoInfoActivity">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@ -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=".photo.PhotoSortingActivity">
|
tools:context=".sort.PhotoSortingActivity">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/layout_top"
|
android:id="@+id/layout_top"
|
||||||
|
|||||||
53
app/src/main/res/layout/activity_recovery.xml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?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/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".recovery.RecoveryActivity">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_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:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:text="@string/recovered_files"
|
||||||
|
android:textColor="@color/main_title"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:fontType="bold" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="66dp"
|
||||||
|
app:tabIndicatorHeight="4dp"
|
||||||
|
app:tabMaxWidth="18dp"
|
||||||
|
app:tabMode="fixed"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
android:id="@+id/tab_layout"
|
||||||
|
app:tabIndicatorColor="@color/color_title_blue"
|
||||||
|
app:tabIndicatorGravity="center"
|
||||||
|
app:tabBackground="@color/white"/>
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/view_page2"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</LinearLayout>
|
||||||
20
app/src/main/res/layout/fragment_recovery_photo.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?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/recovery_photo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.recoveryphoto.RecoveryPhotoFragment">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/message"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="RecoveryPhotoFragment"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
78
app/src/main/res/layout/one_documents_item.xml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?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/constraint_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_select"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/selector_icon_checkmark_28dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:id="@+id/image_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:src="@drawable/icon_apk"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/image_select" />
|
||||||
|
|
||||||
|
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
android:id="@+id/text_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="6dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/main_title"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:fontType="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/linear_duration"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/image_icon"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="aaaaaaaaaassssssssssssssssssssssssssssssssa" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linear_duration"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:gravity="top"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@id/text_name"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/text_name">
|
||||||
|
|
||||||
|
|
||||||
|
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
android:id="@+id/text_date"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/main_sub_title"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:text="aaaaaaaaaaa" />
|
||||||
|
|
||||||
|
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
android:id="@+id/text_size"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:textColor="@color/main_sub_title"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:text="aaaaaaaaaaa" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
24
app/src/main/res/layout/tab_layout_item.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?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="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
android:id="@+id/tab_item_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/selector_recovery_file_tab_layout_title"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:fontType="bold" />
|
||||||
|
|
||||||
|
<com.ux.video.file.filerecovery.utils.CustomTextView
|
||||||
|
android:id="@+id/tab_item_count"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/main_sub_title"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:fontType="bold" />
|
||||||
|
</LinearLayout>
|
||||||
@ -86,6 +86,8 @@ wait..</string>
|
|||||||
<string name="view">View</string>
|
<string name="view">View</string>
|
||||||
<string name="not_found">Sorry!No %s found!</string>
|
<string name="not_found">Sorry!No %s found!</string>
|
||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
|
<string name="recovered_files">Recovered files</string>
|
||||||
|
<string name="text_counts">(%d)</string>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="filter_date">
|
<string-array name="filter_date">
|
||||||
|
|||||||
@ -3,3 +3,9 @@ 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
|
||||||
}
|
}
|
||||||
|
buildscript {
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath("io.objectbox:objectbox-gradle-plugin:4.0.3")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,9 @@ appcompat = "1.7.1"
|
|||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
activity = "1.10.1"
|
activity = "1.10.1"
|
||||||
constraintlayout = "2.2.1"
|
constraintlayout = "2.2.1"
|
||||||
|
lifecycleLivedataKtx = "2.9.4"
|
||||||
|
lifecycleViewmodelKtx = "2.9.4"
|
||||||
|
fragmentKtx = "1.8.9"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
@ -22,6 +25,9 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
|
|||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
|
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
|
||||||
|
androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||||
|
androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||