Commit 9918d474 authored by wanglei's avatar wanglei

feat:白包修改

parents f14af91b 985eb386
......@@ -5,7 +5,7 @@
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
......
......@@ -50,6 +50,7 @@ dependencies {
implementation(libs.coil)
implementation(libs.coil.video)
implementation(libs.coil.gif)
implementation(libs.androidx.datastore.preferences)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
......
......@@ -19,26 +19,36 @@
android:theme="@style/Theme.SolarMasterAce"
tools:targetApi="31">
<activity
android:screenOrientation="portrait"
android:launchMode="singleTop"
android:name=".LaunchActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:screenOrientation="portrait"
android:name=".internalstorage.InternalStorageActivity"
android:exported="false" />
<activity
android:screenOrientation="portrait"
android:name=".filedetails.FileDetailActivity"
android:exported="false"
android:launchMode="singleTop" />
<activity
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:name=".filebrowser.FileBrowserActivity"
android:exported="false" />
android:exported="false"
android:launchMode="singleTop" />
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
......
package com.zxhy.solarmasterace
import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.zxhy.solarmasterace.databinding.ActivityLaunchBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class LaunchActivity : AppCompatActivity() {
private lateinit var binding: ActivityLaunchBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityLaunchBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
lifecycleScope.launch(Dispatchers.Main) {
var process = 0
while (process != 100) {
process += 10
binding.progressH.setProgress(process, true)
delay(200)
}
startActivity(Intent(this@LaunchActivity, MainActivity::class.java))
finish()
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.widget.AdapterView
......@@ -77,6 +78,5 @@ class MainActivity : AppCompatActivity() {
})
requestStoreFollow(launcher, disAgreeAction = {}, agreeAction = {})
}
}
\ No newline at end of file
......@@ -6,7 +6,6 @@ interface AdapterCommonDataFunction {
abstract fun setData(data: List<FileBean>)
abstract fun addData(data: List<FileBean>)
abstract fun addDataFinish(data: List<FileBean>)
abstract fun clearData()
abstract fun removeData(data: List<FileBean>)
abstract fun getSelectData(): List<FileBean>
......
......@@ -21,17 +21,9 @@ abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(),
@SuppressLint("NotifyDataSetChanged")
override fun addData(data: List<FileBean>) {
fileList.addAll(data)
if (firstRefresh) {
notifyDataSetChanged()
firstRefresh = false
}
}
@SuppressLint("NotifyDataSetChanged")
override fun addDataFinish(data: List<FileBean>) {
fileList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
override fun clearData() {
......@@ -61,12 +53,11 @@ abstract class CommonAdapter<T : ViewHolder?>() : RecyclerView.Adapter<T>(),
@SuppressLint("NotifyDataSetChanged")
override fun toggleSelect(select: Boolean) {
fileList.mapIndexed { index, fileBean ->
if (fileBean.isSelect != select) {
fileBean.isSelect = select
notifyItemChanged(index, "单条刷新")
}
fileList.forEach {
fileBean ->
fileBean.isSelect=select
}
notifyDataSetChanged()
}
......
......@@ -174,9 +174,10 @@ fun File.isDocument(): Boolean {
return isWord() or isExcel() or isPPt() or isPdf() or isTxt()
}
fun File.toFileBean(): FileBean {
fun File.toFileBean(id: Long = 0): FileBean {
val timeE = SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).format(lastModified())
return FileBean(
id = id,
name = name,
path = absolutePath,
size = length(),
......
package com.zxhy.solarmasterace.datastore
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "file_count")
val DUP_IMAGE_COUNTER_KEY = intPreferencesKey("dup_image_counter")
val LARGE_FILES_COUNTER_KEY = intPreferencesKey("large_files_counter")
val EMPTY_FILE_COUNTER_KEY = intPreferencesKey("empty_file_counter")
suspend fun Context.saveFileCount(key: Preferences.Key<Int>, count: Int) {
dataStore.edit {
when (key) {
DUP_IMAGE_COUNTER_KEY -> it[DUP_IMAGE_COUNTER_KEY] = count
LARGE_FILES_COUNTER_KEY -> it[LARGE_FILES_COUNTER_KEY] = count
EMPTY_FILE_COUNTER_KEY -> it[EMPTY_FILE_COUNTER_KEY] = count
}
}
}
suspend fun Context.queryFileCount(key: Preferences.Key<Int>, action: (count: Int) -> Unit) {
val flow = when (key) {
DUP_IMAGE_COUNTER_KEY -> dataStore.data.map { it[DUP_IMAGE_COUNTER_KEY] }
LARGE_FILES_COUNTER_KEY -> dataStore.data.map { it[LARGE_FILES_COUNTER_KEY] }
EMPTY_FILE_COUNTER_KEY -> {
dataStore.data.map { it[EMPTY_FILE_COUNTER_KEY] }
}
else -> null
}
flow?.collect {
if (it != null) {
action.invoke(it)
}
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.zxhy.solarmasterace.filebrowser
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
......@@ -14,6 +15,10 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.databinding.ActivityFileBrowserBinding
import com.zxhy.solarmasterace.datastore.DUP_IMAGE_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.EMPTY_FILE_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.LARGE_FILES_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.saveFileCount
import com.zxhy.solarmasterace.dialog.showLoadingDialog
import com.zxhy.solarmasterace.filedetails.FileDetailActivity
import com.zxhy.solarmasterace.permission.requestStoreFollow
......@@ -72,24 +77,60 @@ class FileBrowserActivity : AppCompatActivity() {
private fun showBrowser() {
when (title) {
"Duplicate picture" -> dupImageMode()
"Scan large files" -> largeFileMode()
"Scan empty file" -> emptyFileMode()
"Image" -> imageMode()
"Video" -> videoMode()
"Audio" -> audioMode()
"Apk" -> apkMode()
"Zip" -> zipMode()
"Log file" -> logFileMode()
"Word" -> wordMode()
"Excel" -> excelMode()
"PPT" -> pptMode()
"PDF" -> pdfMode()
"TXT" -> txtMode()
"Documents" -> documentMode()
"Audio" -> audioMode()//
"Apk" -> apkMode()//
"Zip" -> zipMode()//
"Log file" -> logFileMode()//
"Word" -> wordMode()//
"Excel" -> excelMode()//
"PPT" -> pptMode()//
"PDF" -> pdfMode()//
"TXT" -> txtMode()//
"Documents" -> documentMode()//
"Scan large files" -> largeFileMode()//
"Scan empty file" -> emptyFileMode()//
"Duplicate picture" -> dupImageMode()
}
}
@SuppressLint("SetTextI18n")
private fun loadImageFile() {
val dialog = showLoadingDialog()
fileGridAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
imageFile(lifecycleScope,
onDo = { data ->
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
waitList.addAll(data)
fileGridAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
private fun documentMode() {
cardUi()
......@@ -99,18 +140,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadDocumentFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
documentFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -128,18 +177,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadTxtFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
txtFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -157,18 +214,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadPdfFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
pdfFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -187,18 +252,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadPptFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
pptFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -267,18 +340,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadExcelFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
excelFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -323,47 +404,65 @@ class FileBrowserActivity : AppCompatActivity() {
loadImageFile()
}
@SuppressLint("SetTextI18n")
private fun loadWordFile() {
private fun loadLargeFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
wordFile(
var doLaunch = false
val waitList = ArrayList<FileBean>()
largeFile(
lifecycleScope,
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
saveFileCount(LARGE_FILES_COUNTER_KEY, count)
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadImageFile() {
private fun loadWordFile() {
val dialog = showLoadingDialog()
fileGridAdapter.clearData()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
imageFile(
wordFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addData(data)
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -373,22 +472,31 @@ class FileBrowserActivity : AppCompatActivity() {
}
}
@SuppressLint("SetTextI18n")
private fun loadVideoFile() {
val dialog = showLoadingDialog()
fileGridAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
videoFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
fileGridAdapter.addDataFinish(data)
waitList.addAll(data)
fileGridAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -399,23 +507,7 @@ class FileBrowserActivity : AppCompatActivity() {
}
private fun largeFileMode() {
binding.tvTip1.visibility = View.VISIBLE
binding.tvTip2.visibility = View.VISIBLE
cardFileAdapter = CardFileAdapter {
binding.ivAll.isSelected = it
}
binding.rv.adapter = cardFileAdapter
binding.ivAll.setOnClickListener {
it.isSelected = !it.isSelected
cardFileAdapter.toggleSelect(it.isSelected)
}
binding.tvDelete.background =
ContextCompat.getDrawable(this, R.drawable.bg_ff5c67e5_corners)
binding.tvDelete.text = "删除"
binding.tvDelete.setTextColor(ContextCompat.getColor(this, R.color.white))
binding.tvDelete.setOnClickListener {
deleteCardFile(cardFileAdapter.getSelectData())
}
cardUi()
loadLargeFile()
}
......@@ -438,47 +530,31 @@ class FileBrowserActivity : AppCompatActivity() {
deleteFiles(files.map { it.file() })
}
@SuppressLint("SetTextI18n")
private fun loadLargeFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
lifecycleScope.launch(Dispatchers.IO) {
largeFile(
onDo = { data ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
}
}
)
}
}
@SuppressLint("SetTextI18n")
private fun loadAudioFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
audioFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -492,18 +568,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadApkFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
apkFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -517,18 +601,26 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadZipFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
zipFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -542,18 +634,27 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadLogFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
logFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
Log.e("TAG", data.toString())
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
......@@ -572,21 +673,30 @@ class FileBrowserActivity : AppCompatActivity() {
private fun loadEmptyFile() {
val dialog = showLoadingDialog()
cardFileAdapter.clearData()
var doLaunch = false
val waitList = ArrayList<FileBean>()
lifecycleScope.launch(Dispatchers.IO) {
emptyFile(
onDo = { data ->
launch(Dispatchers.Main) {
if (doLaunch) {
doLaunch = true
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addData(data)
}
} else {
waitList.addAll(data)
}
},
onFinish = { data, count ->
launch(Dispatchers.Main) {
lifecycleScope.launch(Dispatchers.Main) {
dialog.dismiss()
cardFileAdapter.addDataFinish(data)
waitList.addAll(data)
cardFileAdapter.addData(waitList)
binding.tvTip1.text = "$count items"
binding.ivAll.isSelected = false
showEmptyUi()
saveFileCount(EMPTY_FILE_COUNTER_KEY, count)
}
}
)
......@@ -635,6 +745,8 @@ class FileBrowserActivity : AppCompatActivity() {
dupImageAdapter.setData(data)
binding.ivAll.isSelected = false
showEmptyUi()
saveFileCount(DUP_IMAGE_COUNTER_KEY, data.sumOf { it.dupData.size })
}
}
}
......
package com.zxhy.solarmasterace.internalstorage
import android.annotation.SuppressLint
import android.content.Context
import android.os.Environment
import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.adapter.CommonAdapter
import com.zxhy.solarmasterace.adapter.ItemCardFileViewHolder
......@@ -21,6 +23,7 @@ class FileDirectoryAdapter(
private var currentDir = Environment.getExternalStorageDirectory()
private var isSelectMode = false
private var pageTurn = true
private var operationFile = arrayListOf<FileBean>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemCardFileViewHolder {
return ItemCardFileViewHolder(R.layout.item_card_file.inflate(parent))
......@@ -68,6 +71,18 @@ class FileDirectoryAdapter(
if (!pageTurn) return@setOnClickListener
nextPage(data)
}
//该列表是选中列表
if (operationFile.map { it.path }.contains(data.path)) {
root.setOnClickListener { }
root.setCardBackgroundColor(
ContextCompat.getColor(
context, R.color.color_F4F4F4
)
)
} else {
root.setCardBackgroundColor(ContextCompat.getColor(context, R.color.white))
}
}
} else {
holder.binding.apply {
......@@ -118,4 +133,16 @@ class FileDirectoryAdapter(
return currentDir
}
//当选中选中的列表,无法复制 移动到自身
fun notifyCannotSelect(data: List<FileBean>) {
val selectList = arrayListOf<FileBean>()
selectList.addAll(data)
operationFile = selectList
notifyDataSetChanged()
}
fun clearCannotSelect() {
operationFile = arrayListOf()
}
}
\ No newline at end of file
......@@ -31,8 +31,7 @@ class InternalStorageActivity : AppCompatActivity() {
private val MODE_BROWSE = 0
private val MODE_SELECT = 1
private val MODE_SELECTED_OPERATION = 2
private val MODE_LOCK = -1
private var currentMode = MODE_BROWSE //0普通浏览模式 1可选模式 2选中操作模式 -1无权限锁功能模式
private var currentMode = MODE_BROWSE //0普通浏览模式 1可选模式 2选中操作模式
private lateinit var activityLauncher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) {
......@@ -53,11 +52,13 @@ class InternalStorageActivity : AppCompatActivity() {
}
binding.clArrow.setOnClickListener {
if (this::fileDirectoryAdapter.isInitialized) {
val flag = fileDirectoryAdapter.beforePage()
if (flag)
finish()
}
}
}
private fun showContent() {
isPermissionSet(false)
......@@ -88,6 +89,20 @@ class InternalStorageActivity : AppCompatActivity() {
binding.llAll.visibility = View.GONE
binding.ivWrite.visibility = View.VISIBLE
binding.ivWrite.setOnClickListener {
// showFolderDialog(tittle = "New Folder", newFolder = { name ->
// val dir = fileDirectoryAdapter.getCurrentDir()
// val file = File(dir, name)
// if (!file.exists()) {
// file.mkdir()
// }
// fileDirectoryAdapter.notifyCurrentDir()
// })
switchSelectMode()
}
binding.ivAdd.setOnClickListener {
// switchSelectMode()
showFolderDialog(tittle = "New Folder", newFolder = { name ->
val dir = fileDirectoryAdapter.getCurrentDir()
val file = File(dir, name)
......@@ -97,9 +112,6 @@ class InternalStorageActivity : AppCompatActivity() {
fileDirectoryAdapter.notifyCurrentDir()
})
}
binding.ivAdd.setOnClickListener {
switchSelectMode()
}
binding.ivMore.setOnClickListener {
val fileBeanList = fileDirectoryAdapter.getSelectData()
val fileList = fileBeanList.map { it.file() }
......@@ -148,16 +160,21 @@ class InternalStorageActivity : AppCompatActivity() {
val files = fileDirectoryAdapter.getSelectData().map { it.file() }
deleteFiles(files) {
showCardTip("Successfully deleted!")
switchBrowseMode()
}
}
binding.ivMove.setOnClickListener {
val moveFile = arrayListOf<File>()
fileDirectoryAdapter.getSelectData().map { moveFile.add(it.file()) }
val selectList = fileDirectoryAdapter.getSelectData()
selectList.map { moveFile.add(it.file()) }
fileDirectoryAdapter.notifyCannotSelect(selectList)
switchSelectedOperationMode("Motion", moveFile)
}
binding.ivCopy.setOnClickListener {
val copyFile = arrayListOf<File>()
fileDirectoryAdapter.getSelectData().map { copyFile.add(it.file()) }
val selectList = fileDirectoryAdapter.getSelectData()
selectList.map { copyFile.add(it.file()) }
fileDirectoryAdapter.notifyCannotSelect(selectList)
switchSelectedOperationMode("Copy", copyFile)
}
}
......@@ -185,6 +202,7 @@ class InternalStorageActivity : AppCompatActivity() {
binding.tvDefine.setOnClickListener {
moveFiles(files) {
showCardTip("Successfully moved!")
fileDirectoryAdapter.clearCannotSelect()
switchBrowseMode()
}
}
......@@ -193,6 +211,7 @@ class InternalStorageActivity : AppCompatActivity() {
"Copy" -> {
binding.tvDefine.setOnClickListener {
copyFiles(files) {
fileDirectoryAdapter.clearCannotSelect()
showCardTip("Successfully copied!")
switchBrowseMode()
}
......@@ -200,6 +219,7 @@ class InternalStorageActivity : AppCompatActivity() {
}
}
binding.tvCancel.setOnClickListener {
fileDirectoryAdapter.clearCannotSelect()
switchBrowseMode()
}
}
......@@ -210,7 +230,10 @@ class InternalStorageActivity : AppCompatActivity() {
val dir = fileDirectoryAdapter.getCurrentDir() ?: File("")
files.forEach {
if (it.isFile) {
it.copyTo(File(dir, it.name))
val destFile = File(dir, it.name)
if (!destFile.exists()) {
it.copyTo(destFile)
}
} else {
FileHelper.copyDirectory(it, File(dir, it.name))
}
......@@ -265,7 +288,10 @@ class InternalStorageActivity : AppCompatActivity() {
if (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
when (currentMode) {
MODE_BROWSE -> {
val flag = fileDirectoryAdapter.beforePage()
var flag = true
if (this::fileDirectoryAdapter.isInitialized) {
flag = fileDirectoryAdapter.beforePage()
}
return if (flag) super.dispatchKeyEvent(event) else false
}
......
package com.zxhy.solarmasterace.quicktools
import android.os.Environment
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.lifecycleScope
import com.zxhy.solarmasterace.data.DupFileBean
import com.zxhy.solarmasterace.data.FileBean
import com.zxhy.solarmasterace.data.isApk
......@@ -16,6 +18,8 @@ import com.zxhy.solarmasterace.data.isVideo
import com.zxhy.solarmasterace.data.isWord
import com.zxhy.solarmasterace.data.isZip
import com.zxhy.solarmasterace.data.toFileBean
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.util.Stack
......@@ -52,9 +56,11 @@ fun dupImage(): List<DupFileBean> {
}
fun largeFile(
lifecycleScope: LifecycleCoroutineScope,
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
) {
lifecycleScope.launch(Dispatchers.IO) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
......@@ -69,6 +75,9 @@ fun largeFile(
}
}
onFinish?.invoke(tempList, count)
}
}
fun audioFile(
......@@ -295,15 +304,17 @@ fun emptyFile(
}
fun imageFile(
lifecycleCoroutineScope: LifecycleCoroutineScope,
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
onFinish: ((file: List<FileBean>, count: Long) -> Unit)? = null
) {
lifecycleCoroutineScope.launch(Dispatchers.IO) {
val rootDir = Environment.getExternalStorageDirectory()
val tempList = arrayListOf<FileBean>()
var count = 0
var count = 0L
FileHelper.linkedLisTraverseFolder(rootDir) {
if (it.isImage()) {
tempList.add(it.toFileBean())
tempList.add(it.toFileBean(count))
count++
if (tempList.size == 10) {
onDo?.invoke(tempList)
......@@ -312,8 +323,10 @@ fun imageFile(
}
}
onFinish?.invoke(tempList, count)
}
}
fun videoFile(
onDo: ((file: List<FileBean>) -> Unit)? = null,
onFinish: ((file: List<FileBean>, count: Int) -> Unit)? = null
......
......@@ -83,7 +83,8 @@ object FileHelper {
val currentFile = stackFiles.peek()
val subFiles = currentFile.listFiles()
for (i in subFiles!!.indices) {
if (subFiles != null) {
for (i in subFiles.indices) {
if (subFiles[i].isFile) {
if (!subFiles[i].delete()) {
return false
......@@ -92,6 +93,7 @@ object FileHelper {
stackFiles.push(subFiles[i])
}
}
}
if (currentFile === stackFiles.peek()) {
if (!currentFile.delete()) {
return false
......@@ -108,6 +110,7 @@ object FileHelper {
* @param target 目标文件夹
*/
fun copyDirectory(source: File, target: File) {
try {
if (source.isDirectory) {
if (!target.exists()) target.mkdir()
......@@ -115,8 +118,14 @@ object FileHelper {
copyDirectory(File(source, sub), File(target, sub))
}
} else {
if (!target.exists()) {
source.copyTo(target)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
\ No newline at end of file
package com.zxhy.solarmasterace.tools
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
......@@ -11,6 +12,11 @@ import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.zxhy.solarmasterace.R
import com.zxhy.solarmasterace.databinding.FragmentToolsBinding
import com.zxhy.solarmasterace.datastore.DUP_IMAGE_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.EMPTY_FILE_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.LARGE_FILES_COUNTER_KEY
import com.zxhy.solarmasterace.datastore.queryFileCount
import com.zxhy.solarmasterace.datastore.saveFileCount
import com.zxhy.solarmasterace.filedetails.FileDetailActivity
import com.zxhy.solarmasterace.quicktools.getFilePathByUri
import com.zxhy.solarmasterace.quicktools.recentImage
......@@ -80,6 +86,44 @@ class ToolsFragment : Fragment() {
}
loadRecentImage()
queryFileCounts()
}
@SuppressLint("SetTextI18n")
private fun queryFileCounts() {
lifecycleScope.launch(Dispatchers.Main) {
// context.saveFileCount(DUP_IMAGE_COUNTER_KEY, 100)
context.queryFileCount(DUP_IMAGE_COUNTER_KEY) { count ->
if (count == 0) {
binding.tvDupCout.visibility = View.GONE
} else {
binding.tvDupCout.text = "$count items"
}
}
}
lifecycleScope.launch(Dispatchers.Main) {
// context.saveFileCount(LARGE_FILES_COUNTER_KEY, 200)
context.queryFileCount(LARGE_FILES_COUNTER_KEY) { count ->
if (count == 0) {
binding.tvLargeCount.visibility = View.GONE
} else {
binding.tvLargeCount.text = "$count items"
}
}
}
lifecycleScope.launch(Dispatchers.Main) {
// context.saveFileCount(EMPTY_FILE_COUNTER_KEY, 300)
context.queryFileCount(EMPTY_FILE_COUNTER_KEY) { dupCount ->
if (dupCount == 0) {
binding.tvEmptyCount.visibility = View.GONE
} else {
binding.tvEmptyCount.text = "$dupCount items"
}
}
}
}
override fun onResume() {
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LaunchActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="140dp"
android:layout_height="150dp"
android:layout_marginTop="150dp"
android:src="@mipmap/zsd_589878"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:text="Solar Master Ace"
android:textColor="@color/black"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="@id/iv"
app:layout_constraintRight_toRightOf="@id/iv"
app:layout_constraintTop_toBottomOf="@id/iv"
tools:ignore="HardcodedText" />
<ProgressBar
android:id="@+id/progress_h"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginHorizontal="50dp"
android:layout_marginBottom="36dp"
android:max="100"
android:progress="0"
android:progressTint="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="loading..."
android:textColor="@android:color/background_dark"
android:textSize="15sp"
app:layout_constraintBottom_toTopOf="@id/progress_h"
app:layout_constraintLeft_toLeftOf="@id/progress_h"
app:layout_constraintRight_toRightOf="@id/progress_h"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -65,6 +65,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_dup_cout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
......@@ -132,6 +133,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_large_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
......@@ -200,6 +202,7 @@
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_empty_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
......
......@@ -6,4 +6,6 @@
<color name="color_FF4CE0AB">#FF4CE0AB</color>
<color name="color_FF333333">#FF333333</color>
<color name="color_FF999999">#FF999999</color>
<color name="color_999999">#999999</color>
<color name="color_F4F4F4">#F4F4F4</color>
</resources>
\ No newline at end of file
......@@ -12,6 +12,7 @@ constraintlayout = "2.1.4"
navigationFragmentKtx = "2.7.7"
navigationUiKtx = "2.7.7"
coil = "2.6.0"
datastorePreferences = "1.0.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
......@@ -27,6 +28,7 @@ androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }
coil-video = { group = "io.coil-kt", name = "coil-video", version.ref = "coil" }
coil-gif = { group = "io.coil-kt", name = "coil-gif", version.ref = "coil" }
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastorePreferences" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment