Skip to content

Commit

Permalink
Performed some fixes on Trash Screen (W.I.P)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihai-Cristian Condrea committed Oct 2, 2024
1 parent 6103327 commit ec3dfb4
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 53 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {
applicationId = "com.d4rk.cleaner"
minSdk = 23
targetSdk = 34
versionCode = 130
versionCode = 131
versionName = "2.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += listOf(
Expand Down
47 changes: 32 additions & 15 deletions app/src/main/kotlin/com/d4rk/cleaner/ui/screens/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ fun AnalyzeComposable(imageLoader : ImageLoader , context : Context) {
FilesByDateSection(
filesByDate = filesByDate ,
fileSelectionStates = uiState.fileSelectionStates ,
imageLoader = imageLoader
imageLoader = imageLoader ,
onFileSelectionChange = viewModel::onFileSelectionChange
)
}
}
Expand Down Expand Up @@ -355,6 +356,7 @@ fun FilesByDateSection(
filesByDate : Map<String , List<File>> ,
fileSelectionStates : Map<File , Boolean> ,
imageLoader : ImageLoader ,
onFileSelectionChange : (File , Boolean) -> Unit ,
) {
LazyColumn(
modifier = Modifier.fillMaxSize()
Expand All @@ -365,11 +367,20 @@ fun FilesByDateSection(
sortedDates.forEach { date ->
val files = filesByDate[date] ?: emptyList()
item(key = date) {
DateHeader(files = files , fileSelectionStates = fileSelectionStates)
DateHeader(
files = files ,
fileSelectionStates = fileSelectionStates ,
onFileSelectionChange = onFileSelectionChange
)
}

item(key = "$date-grid") {
FilesGrid(files = files , imageLoader = imageLoader)
FilesGrid(
files = files ,
imageLoader = imageLoader ,
fileSelectionStates = fileSelectionStates ,
onFileSelectionChange = onFileSelectionChange
)
}
}
}
Expand All @@ -379,8 +390,8 @@ fun FilesByDateSection(
fun DateHeader(
files : List<File> ,
fileSelectionStates : Map<File , Boolean> ,
onFileSelectionChange : (File , Boolean) -> Unit ,
) {
val viewModel : HomeViewModel = viewModel()
Row(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -397,7 +408,7 @@ fun DateHeader(
checked = allFilesForDateSelected ,
onCheckedChange = { isChecked ->
files.forEach { file ->
viewModel.onFileSelectionChange(file , isChecked)
onFileSelectionChange(file , isChecked)
}
})
}
Expand All @@ -407,23 +418,29 @@ fun DateHeader(
fun FilesGrid(
files : List<File> ,
imageLoader : ImageLoader ,
fileSelectionStates : Map<File , Boolean> ,
onFileSelectionChange : (File , Boolean) -> Unit ,
) {
Box(
modifier = Modifier.fillMaxSize()
) {
NonLazyGrid(
columns = 3 , itemCount = files.size , modifier = Modifier.padding(horizontal = 8.dp)
) { index ->
FileCard(
file = files[index] , imageLoader = imageLoader
)
val file = files[index]
FileCard(file = file ,
imageLoader = imageLoader ,
isChecked = fileSelectionStates[file] ?: false ,
onCheckedChange = { isChecked -> onFileSelectionChange(file , isChecked) })
}
}
}

@Composable
fun FileCard(file : File , imageLoader : ImageLoader) {
val viewModel : HomeViewModel = viewModel()
fun FileCard(
file : File , imageLoader : ImageLoader , onCheckedChange : (Boolean) -> Unit ,
isChecked : Boolean ,
) {

val context : Context = LocalContext.current
val fileExtension : String = remember(file.name) { getFileExtension(file.name) }
Expand Down Expand Up @@ -484,11 +501,11 @@ fun FileCard(file : File , imageLoader : ImageLoader) {
}
}

Checkbox(checked = viewModel.uiState.value.fileSelectionStates[file] ?: false ,
onCheckedChange = { isChecked ->
viewModel.onFileSelectionChange(file , isChecked)
} ,
modifier = Modifier.align(Alignment.TopEnd))
Checkbox(
checked = isChecked ,
onCheckedChange = onCheckedChange ,
modifier = Modifier.align(Alignment.TopEnd)
)

Text(
text = file.name ,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,16 @@ class HomeViewModel(application : Application) : BaseViewModel(application) {

fun moveToTrash() {
viewModelScope.launch(context = Dispatchers.Default + coroutineExceptionHandler) {
val filesToMove = _uiState.value.fileSelectionStates.filter { it.value }.keys
val filesToMove = _uiState.value.fileSelectionStates.filter { it.value }.keys.toList()
showLoading()
repository.moveToTrash(filesToMove) {
_uiState.value = _uiState.value.copy(
scannedFiles = uiState.value.scannedFiles.filterNot { filesToMove.contains(it) } ,
selectedFileCount = 0 ,
allFilesSelected = false ,
fileSelectionStates = emptyMap()
)
_uiState.value =
_uiState.value.copy(scannedFiles = uiState.value.scannedFiles.filterNot { existingFile ->
filesToMove.any { movedFile -> existingFile.absolutePath == movedFile.absolutePath }
} ,
selectedFileCount = 0 ,
allFilesSelected = false ,
fileSelectionStates = emptyMap())
updateStorageInfo()
}
hideLoading()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.d4rk.cleaner.ui.screens.home.repository

import android.app.Application
import android.os.Environment
import com.d4rk.cleaner.data.datastore.DataStore
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.utils.cleaning.FileScanner
Expand All @@ -11,7 +12,7 @@ import java.io.File
class HomeRepository(
dataStore : DataStore , application : Application ,
) : HomeRepositoryImplementation(application) {
private val fileScanner = FileScanner(dataStore , application.resources)
private val fileScanner = FileScanner(dataStore , application)

suspend fun getStorageInfo(onSuccess : (UiHomeModel) -> Unit) {
withContext(Dispatchers.IO) {
Expand Down Expand Up @@ -45,8 +46,16 @@ class HomeRepository(

suspend fun getTrashFiles() : List<File> {
return withContext(Dispatchers.IO) {
val trashDir = File(application.filesDir , "trash")
if (trashDir.exists()) trashDir.listFiles()?.toList() ?: emptyList() else emptyList()
val trashDir = File(
application.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) , "Trash"
)

if (trashDir.exists()) {
trashDir.listFiles()?.toList() ?: emptyList()
}
else {
return@withContext emptyList()
}
}
}

Expand All @@ -59,9 +68,9 @@ class HomeRepository(
}
}

suspend fun moveToTrash(filesToMove : Set<File> , onSuccess : () -> Unit) {
suspend fun moveToTrash(filesToMove : List<File> , onSuccess : () -> Unit) {
withContext(Dispatchers.IO) {
moveToTrash(filesToMove)
moveToTrash(filesToMove) // Call the updated function below
withContext(Dispatchers.Main) {
onSuccess()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.d4rk.cleaner.ui.screens.home.repository

import android.app.Application
import android.media.MediaScannerConnection
import android.os.Environment
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.utils.cleaning.StorageUtils
import java.io.File
Expand Down Expand Up @@ -29,15 +31,30 @@ abstract class HomeRepositoryImplementation(val application : Application) {
}
}

fun moveToTrash(filesToMove : Set<File>) {
val trashDir = File(application.filesDir , "trash")
/**
* Moves the given files to the trash directory.
*
* @param filesToMove The list of files to move to the trash.
*/
fun moveToTrash(filesToMove : List<File>) {
val trashDir = File(
application.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) , "Trash"
)
if (! trashDir.exists()) {
trashDir.mkdirs()
}

filesToMove.forEach { file ->
val destination = File(trashDir , file.name)
if (file.exists()) {
file.renameTo(destination)
if (file.renameTo(destination)) {
MediaScannerConnection.scanFile(
application ,
arrayOf(destination.absolutePath , file.absolutePath) ,
null ,
null
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ fun TrashScreen(activity : TrashActivity) {
trashFiles = uiState.trashFiles ,
imageLoader ,
uiState = uiState ,
viewModel = viewModel
)

TwoRowButtons(enabled = enabled , onStartButtonClick = {
viewModel.restoreFromTrash()
} , onStartButtonIcon = Icons.Outlined.Delete , onEndButtonClick = {
// TODO:
// TODO: for restore
} , onEndButtonIcon = Icons.Outlined.DeleteForever)
}
}
Expand All @@ -99,6 +100,7 @@ fun TrashItemsList(
trashFiles : List<File> ,
imageLoader : ImageLoader ,
uiState : UiTrashModel ,
viewModel : TrashViewModel ,
) {
val filesByDate = remember(trashFiles) {
trashFiles.groupBy { file ->
Expand All @@ -109,6 +111,7 @@ fun TrashItemsList(
FilesByDateSection(
filesByDate = filesByDate ,
fileSelectionStates = uiState.fileSelectionStates ,
imageLoader = imageLoader
imageLoader = imageLoader ,
onFileSelectionChange = viewModel::onFileSelectionChange
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.io.File

class TrashViewModel(application: Application) : BaseViewModel(application) {
private val repository = HomeRepository(DataStore(application) , application) // Shared repository
class TrashViewModel(application : Application) : BaseViewModel(application) {
private val repository = HomeRepository(DataStore(application) , application)
private val _uiState = MutableStateFlow(UiTrashModel())
val uiState: StateFlow<UiTrashModel> = _uiState
val uiState : StateFlow<UiTrashModel> = _uiState

init {
loadTrashItems()
Expand All @@ -30,13 +30,11 @@ class TrashViewModel(application: Application) : BaseViewModel(application) {
}


fun onFileSelectionChange(file: File , isChecked: Boolean) {
fun onFileSelectionChange(file : File , isChecked : Boolean) {
viewModelScope.launch(coroutineExceptionHandler) {
val updatedSelections = _uiState.value.fileSelectionStates + (file to isChecked)
_uiState.value = _uiState.value.copy(
fileSelectionStates = updatedSelections,
selectedFileCount = updatedSelections.count { it.value }
)
_uiState.value = _uiState.value.copy(fileSelectionStates = updatedSelections ,
selectedFileCount = updatedSelections.count { it.value })
}
}

Expand Down
25 changes: 15 additions & 10 deletions app/src/main/kotlin/com/d4rk/cleaner/utils/cleaning/FileScanner.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.d4rk.cleaner.utils.cleaning

import android.content.res.Resources
import android.app.Application
import android.os.Environment
import com.d4rk.cleaner.R
import com.d4rk.cleaner.constants.cleaning.ExtensionsConstants
Expand All @@ -19,7 +19,7 @@ import java.io.File
* @property dataStore A DataStore instance used for accessing user preferences.
* @property resources A Resources instance used for accessing string arrays that define file types.
*/
class FileScanner(private val dataStore : DataStore , private val resources : Resources) {
class FileScanner(private val dataStore : DataStore , val application : Application) {

private var preferences : Map<String , Boolean> = emptyMap()
private var filteredFiles : List<File> = emptyList()
Expand Down Expand Up @@ -65,16 +65,21 @@ class FileScanner(private val dataStore : DataStore , private val resources : Re
val root : File = Environment.getExternalStorageDirectory()
stack.addFirst(root)

val trashDir =
File(application.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS) , "Trash")

while (stack.isNotEmpty()) {
val currentFile : File = stack.removeFirst()

if (currentFile.isDirectory) {
currentFile.listFiles()?.forEach { stack.addLast(it) }
if (! currentFile.absolutePath.startsWith(trashDir.absolutePath)) {
currentFile.listFiles()?.forEach { stack.addLast(it) }
}
}
else {
files.add(currentFile)
}
}

return files
}

Expand All @@ -88,38 +93,38 @@ class FileScanner(private val dataStore : DataStore , private val resources : Re
return@with when (key) {
GENERIC_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.generic_extensions)
application.resources.getStringArray(R.array.generic_extensions)
return@with value && extensions.map { it.removePrefix(prefix = ".") }
.contains(file.extension)
}

ARCHIVE_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.archive_extensions)
application.resources.getStringArray(R.array.archive_extensions)
return@with value && extensions.contains(file.extension)
}

APK_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.apk_extensions)
application.resources.getStringArray(R.array.apk_extensions)
return@with value && extensions.contains(file.extension)
}

AUDIO_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.audio_extensions)
application.resources.getStringArray(R.array.audio_extensions)
return@with value && extensions.contains(file.extension)
}

VIDEO_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.video_extensions)
application.resources.getStringArray(R.array.video_extensions)
return@with value && extensions.contains(file.extension)
}

IMAGE_EXTENSIONS -> {
val extensions : Array<String> =
resources.getStringArray(R.array.image_extensions)
application.resources.getStringArray(R.array.image_extensions)
return@with value && extensions.contains(file.extension)
}

Expand Down
Loading

0 comments on commit ec3dfb4

Please sign in to comment.