Skip to content

Commit

Permalink
Added new info text about the cleaned storage and last scan
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihai-Cristian Condrea committed Oct 20, 2024
1 parent f819e53 commit 9cdf416
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 4 deletions.
22 changes: 22 additions & 0 deletions app/src/main/kotlin/com/d4rk/cleaner/data/datastore/DataStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,28 @@ class DataStore(context: Context) {
}

// Cleaning
private val cleanedSpaceKey = longPreferencesKey(name = "cleaned_space")
val cleanedSpace: Flow<Long> = dataStore.data.map { preferences ->
preferences[cleanedSpaceKey] ?: 0L
}

suspend fun addCleanedSpace(space: Long) {
dataStore.edit { preferences ->
preferences[cleanedSpaceKey] = (preferences[cleanedSpaceKey] ?: 0L) + space
}
}

private val lastScanTimestampKey = longPreferencesKey(name = "last_scan_timestamp")
val lastScanTimestamp: Flow<Long> = dataStore.data.map { preferences ->
preferences[lastScanTimestampKey] ?: 0L
}

suspend fun saveLastScanTimestamp(timestamp: Long) {
dataStore.edit { preferences ->
preferences[lastScanTimestampKey] = timestamp
}
}

private val trashFilePathsKey = stringSetPreferencesKey("trash_file_paths")

val trashFilePaths: Flow<Set<String>> = dataStore.data.map { preferences ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ data class UiHomeModel(
var usedStorageFormatted : String = "" ,
var totalStorageFormatted : String = "" ,
var analyzeState : UiAnalyzeModel = UiAnalyzeModel() ,
var daysFromLastScan : Int = 0,
val cleanedSpace: String = "0 KB",
var isRescanDialogVisible : Boolean = false ,
)

Expand Down
20 changes: 20 additions & 0 deletions app/src/main/kotlin/com/d4rk/cleaner/ui/components/Dividers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.d4rk.cleaner.ui.components

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun VerticalDivider() {
Box(
modifier = Modifier
.fillMaxHeight()
.width(1.dp)
.background(MaterialTheme.colorScheme.onSurface.copy(alpha = 0.2f))
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.d4rk.cleaner.ui.components.navigation

import android.view.SoundEffectConstants
import android.view.View
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Icon
Expand All @@ -14,6 +15,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
Expand Down Expand Up @@ -55,7 +57,9 @@ fun BottomNavigationBar(
},
label = {
if (showLabels) Text(
text = stringResource(id = screen.title)
text = stringResource(id = screen.title),
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
)
},
selected = currentRoute == screen.route,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -534,6 +535,7 @@ fun FileCard(
overflow = TextOverflow.Ellipsis ,
modifier = Modifier
.fillMaxWidth()
.basicMarquee()
.background(
color = Color.Black.copy(alpha = 0.4f)
)
Expand Down
68 changes: 68 additions & 0 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 @@ -5,11 +5,19 @@ import android.content.Context
import android.view.View
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
Expand All @@ -18,16 +26,21 @@ import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.ImageLoader
import coil.disk.DiskCache
import coil.memory.MemoryCache
import com.d4rk.cleaner.R
import com.d4rk.cleaner.data.model.ui.error.UiErrorModel
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.ui.components.CircularDeterminateIndicator
import com.d4rk.cleaner.ui.components.VerticalDivider
import com.d4rk.cleaner.ui.components.dialogs.ErrorAlertDialog
import com.d4rk.cleaner.ui.screens.analyze.AnalyzeScreen
import com.d4rk.cleaner.utils.PermissionsUtils
Expand Down Expand Up @@ -74,6 +87,13 @@ fun HomeScreen() {
onClick = {
viewModel.analyze()
})
LastScanInfo(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 16.dp) ,
cleanedSpace = uiState.cleanedSpace ,
daysFromLastScan = uiState.daysFromLastScan ,
)
}

Crossfade(
Expand All @@ -94,4 +114,52 @@ fun HomeScreen() {
}
}
}
}

@Composable
fun LastScanInfo(
modifier : Modifier = Modifier ,
cleanedSpace : String ,
daysFromLastScan : Int ,
) {
val context = LocalContext.current

Row(
modifier = modifier
.fillMaxWidth()
.height(IntrinsicSize.Min)
.padding(horizontal = 16.dp , vertical = 8.dp) ,
horizontalArrangement = Arrangement.SpaceAround ,
verticalAlignment = Alignment.CenterVertically
) {
InfoColumn(
title = stringResource(id = R.string.cleaned_space) ,
value = cleanedSpace ,
isRecent = false
)

VerticalDivider()

InfoColumn(
title = stringResource(id = R.string.last_scan) ,
value = context.getString(R.string.last_scan_days_ago , daysFromLastScan) ,
isRecent = daysFromLastScan <= 2
)
}
}

@Composable
fun InfoColumn(title : String , value : String , isRecent : Boolean) {
Column(
horizontalAlignment = Alignment.CenterHorizontally , modifier = Modifier.wrapContentSize()
) {
Text(text = title , style = MaterialTheme.typography.bodySmall)
Text(
text = value ,
style = MaterialTheme.typography.bodyMedium ,
color = if (isRecent) Color.Green else MaterialTheme.colorScheme.onSurface ,
maxLines = 2 ,
overflow = TextOverflow.Ellipsis
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.d4rk.cleaner.data.datastore.DataStore
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.ui.screens.home.repository.HomeRepository
import com.d4rk.cleaner.ui.viewmodel.BaseViewModel
import com.d4rk.cleaner.utils.cleaning.StorageUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -35,6 +36,7 @@ class HomeViewModel(application : Application) : BaseViewModel(application) {
private fun prepareScreenData() {
updateStorageInfo()
populateFileTypesData()
loadCleanedSpaceAndLastScan()
}

/**
Expand All @@ -54,6 +56,18 @@ class HomeViewModel(application : Application) : BaseViewModel(application) {
}
}

private fun loadCleanedSpaceAndLastScan() {
viewModelScope.launch(coroutineExceptionHandler) {
repository.dataStore.cleanedSpace.collect { cleanedSpace ->
_uiState.update { it.copy(cleanedSpace = StorageUtils.formatSize(cleanedSpace)) }
}

repository.getLastScanInfo { daysFromLastScan ->
_uiState.update { it.copy(daysFromLastScan = daysFromLastScan) }
}
}
}

/**
* Initiates file analysis and updates the UI state with the results.
*/
Expand Down Expand Up @@ -178,6 +192,9 @@ class HomeViewModel(application : Application) : BaseViewModel(application) {
val filesToDelete =
_uiState.value.analyzeState.fileSelectionMap.filter { it.value }.keys
showLoading()

val totalCleanedSpace = filesToDelete.sumOf { it.length() } // Calculate cleaned space

repository.deleteFiles(filesToDelete) {
_uiState.update { currentUiState ->
currentUiState.copy(analyzeState = currentUiState.analyzeState.copy(
Expand All @@ -191,6 +208,10 @@ class HomeViewModel(application : Application) : BaseViewModel(application) {
))
}
updateStorageInfo()
viewModelScope.launch(Dispatchers.IO) {
repository.dataStore.addCleanedSpace(totalCleanedSpace)
repository.dataStore.saveLastScanTimestamp(System.currentTimeMillis())
}
}
hideLoading()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.d4rk.cleaner.data.model.ui.screens.FileTypesData
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.utils.cleaning.FileScanner
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
import java.io.File

Expand Down Expand Up @@ -35,6 +36,17 @@ class HomeRepository(
}
}

suspend fun getLastScanInfo(onSuccess: (Int) -> Unit) {
withContext(Dispatchers.IO) {
dataStore.lastScanTimestamp.firstOrNull()?.let { timestamp ->
val daysFromLastScan = calculateDaysSince(timestamp)
withContext(Dispatchers.Main) {
onSuccess(daysFromLastScan)
}
}
}
}

/**
* Retrieves file types data from resources.
* @param onSuccess Callback function to be invoked with the file types data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.d4rk.cleaner.data.model.ui.screens.FileTypesData
import com.d4rk.cleaner.data.model.ui.screens.UiHomeModel
import com.d4rk.cleaner.utils.cleaning.StorageUtils
import java.io.File
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

Expand All @@ -34,6 +35,16 @@ abstract class HomeRepositoryImplementation(
}
}

fun calculateDaysSince(timestamp: Long): Int {
if (timestamp == 0L) return 0

val currentTime = System.currentTimeMillis()
val differenceInMillis = currentTime - timestamp
val days = TimeUnit.MILLISECONDS.toDays(differenceInMillis).toInt()

return days
}

suspend fun getFileTypesDataFromResources() : FileTypesData {
return suspendCoroutine { continuation ->
val apkExtensions =
Expand All @@ -60,7 +71,6 @@ abstract class HomeRepositoryImplementation(
}
}


fun deleteFiles(filesToDelete : Set<File>) {
filesToDelete.forEach { file ->
if (file.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -267,7 +268,8 @@ fun StorageBreakdownItem(icon: String, size: Long, modifier: Modifier = Modifier
Text(
text = icon,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
modifier = Modifier.basicMarquee(),
)
Text(text = formatSize(size), style = MaterialTheme.typography.bodySmall)
}
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
<string name="home">Home</string>
<string name="delete_forever">Delete forever</string>
<string name="move_to_trash">Move to trash</string>

<string name="cleaned_space">Cleaned Space:</string>
<string name="last_scan">Last Scan:</string>
<string name="last_scan_days_ago">%1$d days ago</string>
<string name="delete_forever_title">Delete Forever</string>
<string name="delete_forever_message">Are you sure you want to delete these files forever? This action cannot be undone.</string>
<string name="move_to_trash_title">Move to Trash</string>
Expand Down

0 comments on commit 9cdf416

Please sign in to comment.