Add basic storage usage info to "Data and storage" settings screen

This commit is contained in:
arkon 2023-10-29 16:57:38 -04:00
parent ce7bf396eb
commit cb8ea5eab0
4 changed files with 71 additions and 11 deletions

View file

@ -4,12 +4,15 @@ import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Environment
import android.text.format.Formatter
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@ -32,6 +35,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
import eu.kanade.presentation.permissions.PermissionRequestHelper
import eu.kanade.presentation.util.relativeTimeSpanString
import eu.kanade.tachiyomi.R
@ -41,6 +46,7 @@ import eu.kanade.tachiyomi.data.backup.BackupFileValidator
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.toast
@ -373,22 +379,24 @@ object SettingsDataScreen : SearchableSettings {
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
val chapterCache = remember { Injekt.get<ChapterCache>() }
var readableSizeSema by remember { mutableIntStateOf(0) }
val readableSize = remember(readableSizeSema) { chapterCache.readableSize }
var cacheReadableSizeSema by remember { mutableIntStateOf(0) }
val cacheReadableSize = remember(cacheReadableSizeSema) { chapterCache.readableSize }
return Preference.PreferenceGroup(
title = stringResource(R.string.label_data),
preferenceItems = listOf(
getStorageInfoPref(cacheReadableSize),
Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_clear_chapter_cache),
subtitle = stringResource(R.string.used_cache, readableSize),
subtitle = stringResource(R.string.used_cache, cacheReadableSize),
onClick = {
scope.launchNonCancellable {
try {
val deletedFiles = chapterCache.clear()
withUIContext {
context.toast(context.getString(R.string.cache_deleted, deletedFiles))
readableSizeSema++
cacheReadableSizeSema++
}
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e)
@ -404,6 +412,33 @@ object SettingsDataScreen : SearchableSettings {
),
)
}
@Composable
fun getStorageInfoPref(
chapterCacheReadableSize: String,
): Preference.PreferenceItem.CustomPreference {
val context = LocalContext.current
val available = remember {
Formatter.formatFileSize(context, DiskUtil.getAvailableStorageSpace(Environment.getDataDirectory()))
}
val total = remember {
Formatter.formatFileSize(context, DiskUtil.getTotalStorageSpace(Environment.getDataDirectory()))
}
return Preference.PreferenceItem.CustomPreference(
title = stringResource(R.string.pref_storage_usage),
) {
BasePreferenceWidget(
title = stringResource(R.string.pref_storage_usage),
subcomponent = {
// TODO: downloads, SD cards, bar representation?, i18n
Box(modifier = Modifier.padding(horizontal = PrefsHorizontalPadding)) {
Text(text = "Available: $available / $total (chapter cache: $chapterCacheReadableSize)")
}
},
)
}
}
}
private data class MissingRestoreComponents(

View file

@ -28,6 +28,30 @@ object DiskUtil {
return size
}
/**
* Gets the total space for the disk that a file path points to, in bytes.
*/
fun getTotalStorageSpace(file: File): Long {
return try {
val stat = StatFs(file.absolutePath)
stat.blockCountLong * stat.blockSizeLong
} catch (_: Exception) {
-1L
}
}
/**
* Gets the available space for the disk that a file path points to, in bytes.
*/
fun getAvailableStorageSpace(file: File): Long {
return try {
val stat = StatFs(file.absolutePath)
stat.availableBlocksLong * stat.blockSizeLong
} catch (_: Exception) {
-1L
}
}
/**
* Gets the available space for the disk that a file path points to, in bytes.
*/

View file

@ -35,7 +35,7 @@ interface Preference<T> {
/**
* A preference used for internal app state that isn't really a user preference
* and therefore should not be inplaces like backips.
* and therefore should not be in places like backups.
*/
fun isAppState(key: String): Boolean {
return key.startsWith(APP_STATE_PREFIX)

View file

@ -506,6 +506,13 @@
<string name="restoring_backup_canceled">Canceled restore</string>
<string name="backup_info">You should keep copies of backups in other places as well. Backups may contain sensitive data including any stored passwords; be careful if sharing.</string>
<string name="last_auto_backup_info">Last automatically backed up: %s</string>
<string name="label_data">Data</string>
<string name="pref_storage_usage">Storage usage</string>
<string name="pref_clear_chapter_cache">Clear chapter cache</string>
<string name="used_cache">Used: %1$s</string>
<string name="cache_deleted">Cache cleared. %1$d files have been deleted</string>
<string name="cache_delete_error">Error occurred while clearing</string>
<string name="pref_auto_clear_chapter_cache">Clear chapter cache on app launch</string>
<!-- Sync section -->
<string name="syncing_library">Syncing library</string>
@ -521,12 +528,6 @@
<string name="pref_reset_user_agent_string">Reset default user agent string</string>
<string name="requires_app_restart">Requires app restart to take effect</string>
<string name="cookies_cleared">Cookies cleared</string>
<string name="label_data">Data</string>
<string name="pref_clear_chapter_cache">Clear chapter cache</string>
<string name="used_cache">Used: %1$s</string>
<string name="cache_deleted">Cache cleared. %1$d files have been deleted</string>
<string name="cache_delete_error">Error occurred while clearing</string>
<string name="pref_auto_clear_chapter_cache">Clear chapter cache on app launch</string>
<string name="pref_invalidate_download_cache">Invalidate downloads index</string>
<string name="pref_invalidate_download_cache_summary">Force app to recheck downloaded chapters</string>
<string name="download_cache_invalidated">Downloads index invalidated</string>