2022-10-15 17:38:01 +02:00
|
|
|
package eu.kanade.presentation.more.settings.screen
|
|
|
|
|
2023-10-26 19:43:42 +02:00
|
|
|
import android.content.ActivityNotFoundException
|
2022-10-20 23:48:13 +02:00
|
|
|
import android.content.Context
|
2022-10-15 17:38:01 +02:00
|
|
|
import android.content.Intent
|
|
|
|
import android.net.Uri
|
2023-10-29 21:57:38 +01:00
|
|
|
import android.os.Environment
|
|
|
|
import android.text.format.Formatter
|
2022-10-15 17:38:01 +02:00
|
|
|
import android.widget.Toast
|
2023-12-09 22:50:02 +01:00
|
|
|
import androidx.activity.compose.ManagedActivityResultLauncher
|
2022-10-15 17:38:01 +02:00
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
2022-10-18 15:35:10 +02:00
|
|
|
import androidx.compose.foundation.layout.Box
|
2023-05-06 18:18:52 +02:00
|
|
|
import androidx.compose.foundation.layout.Column
|
2023-10-29 21:57:38 +01:00
|
|
|
import androidx.compose.foundation.layout.padding
|
2023-05-06 18:18:52 +02:00
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
|
import androidx.compose.foundation.verticalScroll
|
2022-10-15 17:38:01 +02:00
|
|
|
import androidx.compose.material3.AlertDialog
|
|
|
|
import androidx.compose.material3.Text
|
|
|
|
import androidx.compose.material3.TextButton
|
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
import androidx.compose.runtime.ReadOnlyComposable
|
|
|
|
import androidx.compose.runtime.getValue
|
2023-05-27 15:22:31 +02:00
|
|
|
import androidx.compose.runtime.mutableIntStateOf
|
2022-10-15 17:38:01 +02:00
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
import androidx.compose.runtime.remember
|
|
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
|
|
|
import androidx.compose.runtime.setValue
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
import androidx.compose.ui.platform.LocalContext
|
2023-10-26 19:43:42 +02:00
|
|
|
import androidx.core.net.toUri
|
2023-11-05 23:13:51 +01:00
|
|
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
|
|
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
2023-10-26 19:43:42 +02:00
|
|
|
import com.hippo.unifile.UniFile
|
2022-10-15 17:38:01 +02:00
|
|
|
import eu.kanade.presentation.more.settings.Preference
|
2023-11-05 23:13:51 +01:00
|
|
|
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
2023-10-29 21:57:38 +01:00
|
|
|
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
|
|
|
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
2023-10-29 17:03:46 +01:00
|
|
|
import eu.kanade.presentation.util.relativeTimeSpanString
|
2023-03-19 22:28:59 +01:00
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
2022-10-15 17:38:01 +02:00
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
2023-03-19 22:28:59 +01:00
|
|
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
2023-10-27 21:06:56 +02:00
|
|
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
2023-10-29 21:57:38 +01:00
|
|
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
2022-10-15 17:38:01 +02:00
|
|
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
2022-11-05 16:56:31 +01:00
|
|
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
2022-10-15 17:38:01 +02:00
|
|
|
import eu.kanade.tachiyomi.util.system.toast
|
2023-10-27 21:06:56 +02:00
|
|
|
import logcat.LogPriority
|
2023-11-19 01:41:33 +01:00
|
|
|
import tachiyomi.core.i18n.stringResource
|
2023-10-27 21:06:56 +02:00
|
|
|
import tachiyomi.core.util.lang.launchNonCancellable
|
|
|
|
import tachiyomi.core.util.lang.withUIContext
|
|
|
|
import tachiyomi.core.util.system.logcat
|
2023-03-05 18:38:31 +01:00
|
|
|
import tachiyomi.domain.backup.service.BackupPreferences
|
2023-10-27 21:06:56 +02:00
|
|
|
import tachiyomi.domain.library.service.LibraryPreferences
|
2023-10-26 19:43:42 +02:00
|
|
|
import tachiyomi.domain.storage.service.StoragePreferences
|
2023-11-18 19:54:56 +01:00
|
|
|
import tachiyomi.i18n.MR
|
2023-11-19 01:41:33 +01:00
|
|
|
import tachiyomi.presentation.core.i18n.stringResource
|
2023-07-20 03:57:22 +02:00
|
|
|
import tachiyomi.presentation.core.util.collectAsState
|
2022-10-15 17:38:01 +02:00
|
|
|
import uy.kohesive.injekt.Injekt
|
|
|
|
import uy.kohesive.injekt.api.get
|
|
|
|
|
2023-10-27 21:06:56 +02:00
|
|
|
object SettingsDataScreen : SearchableSettings {
|
2022-10-15 17:58:24 +02:00
|
|
|
|
2022-10-15 17:38:01 +02:00
|
|
|
@ReadOnlyComposable
|
|
|
|
@Composable
|
2023-11-18 19:54:56 +01:00
|
|
|
override fun getTitleRes() = MR.strings.label_data_storage
|
2022-10-15 17:38:01 +02:00
|
|
|
|
|
|
|
@Composable
|
|
|
|
override fun getPreferences(): List<Preference> {
|
|
|
|
val backupPreferences = Injekt.get<BackupPreferences>()
|
2023-10-26 19:43:42 +02:00
|
|
|
val storagePreferences = Injekt.get<StoragePreferences>()
|
2022-10-15 17:38:01 +02:00
|
|
|
|
|
|
|
return listOf(
|
2023-10-26 19:43:42 +02:00
|
|
|
getStorageLocationPref(storagePreferences = storagePreferences),
|
|
|
|
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
|
|
|
|
|
2023-10-27 21:06:56 +02:00
|
|
|
getBackupAndRestoreGroup(backupPreferences = backupPreferences),
|
|
|
|
getDataGroup(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-10-26 19:43:42 +02:00
|
|
|
@Composable
|
2023-12-09 22:50:02 +01:00
|
|
|
fun storageLocationPicker(
|
|
|
|
storageDirPref: tachiyomi.core.preference.Preference<String>,
|
|
|
|
): ManagedActivityResultLauncher<Uri?, Uri?> {
|
2023-10-26 19:43:42 +02:00
|
|
|
val context = LocalContext.current
|
2023-12-09 22:50:02 +01:00
|
|
|
|
|
|
|
return rememberLauncherForActivityResult(
|
2023-10-26 19:43:42 +02:00
|
|
|
contract = ActivityResultContracts.OpenDocumentTree(),
|
|
|
|
) { uri ->
|
|
|
|
if (uri != null) {
|
|
|
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
|
|
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
|
|
|
|
|
|
context.contentResolver.takePersistableUriPermission(uri, flags)
|
|
|
|
|
2023-11-28 04:21:40 +01:00
|
|
|
UniFile.fromUri(context, uri)?.let {
|
|
|
|
storageDirPref.set(it.uri.toString())
|
|
|
|
}
|
2023-10-26 19:43:42 +02:00
|
|
|
}
|
|
|
|
}
|
2023-12-09 22:50:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun storageLocationText(
|
|
|
|
storageDirPref: tachiyomi.core.preference.Preference<String>,
|
|
|
|
): String {
|
|
|
|
val context = LocalContext.current
|
|
|
|
val storageDir by storageDirPref.collectAsState()
|
|
|
|
|
2023-12-09 23:49:35 +01:00
|
|
|
if (storageDir == storageDirPref.defaultValue()) {
|
|
|
|
return stringResource(MR.strings.no_location_set)
|
|
|
|
}
|
|
|
|
|
2023-12-09 22:50:02 +01:00
|
|
|
return remember(storageDir) {
|
|
|
|
val file = UniFile.fromUri(context, storageDir.toUri())
|
|
|
|
file?.filePath ?: file?.uri?.toString()
|
|
|
|
} ?: stringResource(MR.strings.invalid_location, storageDir)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun getStorageLocationPref(
|
|
|
|
storagePreferences: StoragePreferences,
|
|
|
|
): Preference.PreferenceItem.TextPreference {
|
|
|
|
val context = LocalContext.current
|
|
|
|
val pickStorageLocation = storageLocationPicker(storagePreferences.baseStorageDirectory())
|
2023-10-26 19:43:42 +02:00
|
|
|
|
|
|
|
return Preference.PreferenceItem.TextPreference(
|
|
|
|
title = stringResource(MR.strings.pref_storage_location),
|
2023-12-09 22:50:02 +01:00
|
|
|
subtitle = storageLocationText(storagePreferences.baseStorageDirectory()),
|
2023-10-26 19:43:42 +02:00
|
|
|
onClick = {
|
|
|
|
try {
|
|
|
|
pickStorageLocation.launch(null)
|
|
|
|
} catch (e: ActivityNotFoundException) {
|
|
|
|
context.toast(MR.strings.file_picker_error)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-10-27 21:06:56 +02:00
|
|
|
@Composable
|
|
|
|
private fun getBackupAndRestoreGroup(backupPreferences: BackupPreferences): Preference.PreferenceGroup {
|
|
|
|
val context = LocalContext.current
|
2023-10-29 17:03:46 +01:00
|
|
|
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState()
|
2023-10-27 21:06:56 +02:00
|
|
|
|
|
|
|
return Preference.PreferenceGroup(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.label_backup),
|
2023-10-27 21:06:56 +02:00
|
|
|
preferenceItems = listOf(
|
|
|
|
// Manual actions
|
|
|
|
getCreateBackupPref(),
|
|
|
|
getRestoreBackupPref(),
|
|
|
|
|
|
|
|
// Automatic backups
|
|
|
|
Preference.PreferenceItem.ListPreference(
|
2023-11-19 21:17:19 +01:00
|
|
|
pref = backupPreferences.backupInterval(),
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_backup_interval),
|
2023-10-27 21:06:56 +02:00
|
|
|
entries = mapOf(
|
2023-11-19 01:41:33 +01:00
|
|
|
0 to stringResource(MR.strings.off),
|
|
|
|
6 to stringResource(MR.strings.update_6hour),
|
|
|
|
12 to stringResource(MR.strings.update_12hour),
|
|
|
|
24 to stringResource(MR.strings.update_24hour),
|
|
|
|
48 to stringResource(MR.strings.update_48hour),
|
|
|
|
168 to stringResource(MR.strings.update_weekly),
|
2023-10-27 21:06:56 +02:00
|
|
|
),
|
|
|
|
onValueChanged = {
|
|
|
|
BackupCreateJob.setupTask(context, it)
|
|
|
|
true
|
|
|
|
},
|
|
|
|
),
|
2023-10-29 17:03:46 +01:00
|
|
|
Preference.PreferenceItem.InfoPreference(
|
2023-11-19 01:41:33 +01:00
|
|
|
stringResource(MR.strings.backup_info) + "\n\n" +
|
|
|
|
stringResource(MR.strings.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)),
|
2023-10-29 17:03:46 +01:00
|
|
|
),
|
2023-10-27 21:06:56 +02:00
|
|
|
),
|
2022-10-15 17:38:01 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun getCreateBackupPref(): Preference.PreferenceItem.TextPreference {
|
2023-11-05 23:13:51 +01:00
|
|
|
val navigator = LocalNavigator.currentOrThrow
|
2022-10-15 17:38:01 +02:00
|
|
|
return Preference.PreferenceItem.TextPreference(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_create_backup),
|
|
|
|
subtitle = stringResource(MR.strings.pref_create_backup_summ),
|
2023-11-05 23:13:51 +01:00
|
|
|
onClick = { navigator.push(CreateBackupScreen()) },
|
2022-10-15 17:38:01 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun getRestoreBackupPref(): Preference.PreferenceItem.TextPreference {
|
|
|
|
val context = LocalContext.current
|
|
|
|
var error by remember { mutableStateOf<Any?>(null) }
|
|
|
|
if (error != null) {
|
|
|
|
val onDismissRequest = { error = null }
|
|
|
|
when (val err = error) {
|
|
|
|
is InvalidRestore -> {
|
|
|
|
AlertDialog(
|
|
|
|
onDismissRequest = onDismissRequest,
|
2023-11-19 01:41:33 +01:00
|
|
|
title = { Text(text = stringResource(MR.strings.invalid_backup_file)) },
|
2023-10-18 00:22:55 +02:00
|
|
|
text = { Text(text = listOfNotNull(err.uri, err.message).joinToString("\n\n")) },
|
2022-10-15 17:38:01 +02:00
|
|
|
dismissButton = {
|
|
|
|
TextButton(
|
|
|
|
onClick = {
|
2022-11-05 16:56:31 +01:00
|
|
|
context.copyToClipboard(err.message, err.message)
|
2022-10-15 17:38:01 +02:00
|
|
|
onDismissRequest()
|
|
|
|
},
|
|
|
|
) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_copy_to_clipboard))
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
confirmButton = {
|
|
|
|
TextButton(onClick = onDismissRequest) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_ok))
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
is MissingRestoreComponents -> {
|
|
|
|
AlertDialog(
|
|
|
|
onDismissRequest = onDismissRequest,
|
2023-11-19 01:41:33 +01:00
|
|
|
title = { Text(text = stringResource(MR.strings.pref_restore_backup)) },
|
2022-10-15 17:38:01 +02:00
|
|
|
text = {
|
2023-05-06 18:18:52 +02:00
|
|
|
Column(
|
|
|
|
modifier = Modifier.verticalScroll(rememberScrollState()),
|
|
|
|
) {
|
|
|
|
val msg = buildString {
|
2023-11-19 01:41:33 +01:00
|
|
|
append(stringResource(MR.strings.backup_restore_content_full))
|
2023-05-06 18:18:52 +02:00
|
|
|
if (err.sources.isNotEmpty()) {
|
2023-11-19 01:41:33 +01:00
|
|
|
append("\n\n").append(stringResource(MR.strings.backup_restore_missing_sources))
|
2023-05-06 18:18:52 +02:00
|
|
|
err.sources.joinTo(
|
|
|
|
this,
|
|
|
|
separator = "\n- ",
|
|
|
|
prefix = "\n- ",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
if (err.trackers.isNotEmpty()) {
|
2023-11-19 01:41:33 +01:00
|
|
|
append(
|
|
|
|
"\n\n",
|
|
|
|
).append(stringResource(MR.strings.backup_restore_missing_trackers))
|
2023-05-06 18:18:52 +02:00
|
|
|
err.trackers.joinTo(
|
|
|
|
this,
|
|
|
|
separator = "\n- ",
|
|
|
|
prefix = "\n- ",
|
|
|
|
)
|
|
|
|
}
|
2022-10-20 23:48:13 +02:00
|
|
|
}
|
2023-05-06 18:18:52 +02:00
|
|
|
Text(text = msg)
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
confirmButton = {
|
|
|
|
TextButton(
|
|
|
|
onClick = {
|
2023-03-19 22:28:59 +01:00
|
|
|
BackupRestoreJob.start(context, err.uri)
|
2022-10-15 17:38:01 +02:00
|
|
|
onDismissRequest()
|
|
|
|
},
|
|
|
|
) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_restore))
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
else -> error = null // Unknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-20 23:48:13 +02:00
|
|
|
val chooseBackup = rememberLauncherForActivityResult(
|
|
|
|
object : ActivityResultContracts.GetContent() {
|
|
|
|
override fun createIntent(context: Context, input: String): Intent {
|
|
|
|
val intent = super.createIntent(context, input)
|
2023-11-19 01:41:33 +01:00
|
|
|
return Intent.createChooser(intent, context.stringResource(MR.strings.file_select_backup))
|
2022-10-20 23:48:13 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
) {
|
2023-10-18 00:22:55 +02:00
|
|
|
if (it == null) {
|
2023-11-18 19:54:56 +01:00
|
|
|
context.toast(MR.strings.file_null_uri_error)
|
2023-10-18 00:22:55 +02:00
|
|
|
return@rememberLauncherForActivityResult
|
|
|
|
}
|
2022-10-15 17:38:01 +02:00
|
|
|
|
2023-10-18 00:22:55 +02:00
|
|
|
val results = try {
|
|
|
|
BackupFileValidator().validate(context, it)
|
|
|
|
} catch (e: Exception) {
|
|
|
|
error = InvalidRestore(it, e.message.toString())
|
|
|
|
return@rememberLauncherForActivityResult
|
|
|
|
}
|
2022-10-15 17:38:01 +02:00
|
|
|
|
2023-10-18 00:22:55 +02:00
|
|
|
if (results.missingSources.isEmpty() && results.missingTrackers.isEmpty()) {
|
|
|
|
BackupRestoreJob.start(context, it)
|
|
|
|
return@rememberLauncherForActivityResult
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
2023-10-18 00:22:55 +02:00
|
|
|
|
|
|
|
error = MissingRestoreComponents(it, results.missingSources, results.missingTrackers)
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Preference.PreferenceItem.TextPreference(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_restore_backup),
|
|
|
|
subtitle = stringResource(MR.strings.pref_restore_backup_summ),
|
2022-10-15 17:38:01 +02:00
|
|
|
onClick = {
|
2023-03-19 22:28:59 +01:00
|
|
|
if (!BackupRestoreJob.isRunning(context)) {
|
2022-10-15 17:38:01 +02:00
|
|
|
if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
2023-11-18 19:54:56 +01:00
|
|
|
context.toast(MR.strings.restore_miui_warning, Toast.LENGTH_LONG)
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
2022-10-20 23:48:13 +02:00
|
|
|
// no need to catch because it's wrapped with a chooser
|
2022-10-15 17:38:01 +02:00
|
|
|
chooseBackup.launch("*/*")
|
|
|
|
} else {
|
2023-11-18 19:54:56 +01:00
|
|
|
context.toast(MR.strings.restore_in_progress)
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2023-10-27 21:06:56 +02:00
|
|
|
private fun getDataGroup(): Preference.PreferenceGroup {
|
|
|
|
val scope = rememberCoroutineScope()
|
2022-10-15 17:38:01 +02:00
|
|
|
val context = LocalContext.current
|
2023-10-27 21:06:56 +02:00
|
|
|
val libraryPreferences = remember { Injekt.get<LibraryPreferences>() }
|
2022-10-15 17:38:01 +02:00
|
|
|
|
2023-10-27 21:06:56 +02:00
|
|
|
val chapterCache = remember { Injekt.get<ChapterCache>() }
|
2023-10-29 21:57:38 +01:00
|
|
|
var cacheReadableSizeSema by remember { mutableIntStateOf(0) }
|
|
|
|
val cacheReadableSize = remember(cacheReadableSizeSema) { chapterCache.readableSize }
|
2022-10-15 17:38:01 +02:00
|
|
|
|
|
|
|
return Preference.PreferenceGroup(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.label_data),
|
2022-10-15 17:38:01 +02:00
|
|
|
preferenceItems = listOf(
|
2023-10-29 21:57:38 +01:00
|
|
|
getStorageInfoPref(cacheReadableSize),
|
|
|
|
|
2022-10-15 17:38:01 +02:00
|
|
|
Preference.PreferenceItem.TextPreference(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_clear_chapter_cache),
|
|
|
|
subtitle = stringResource(MR.strings.used_cache, cacheReadableSize),
|
2022-10-20 23:48:13 +02:00
|
|
|
onClick = {
|
2023-10-27 21:06:56 +02:00
|
|
|
scope.launchNonCancellable {
|
|
|
|
try {
|
|
|
|
val deletedFiles = chapterCache.clear()
|
|
|
|
withUIContext {
|
2023-11-19 01:41:33 +01:00
|
|
|
context.toast(context.stringResource(MR.strings.cache_deleted, deletedFiles))
|
2023-10-29 21:57:38 +01:00
|
|
|
cacheReadableSizeSema++
|
2023-10-27 21:06:56 +02:00
|
|
|
}
|
|
|
|
} catch (e: Throwable) {
|
|
|
|
logcat(LogPriority.ERROR, e)
|
2023-11-18 19:54:56 +01:00
|
|
|
withUIContext { context.toast(MR.strings.cache_delete_error) }
|
2023-10-27 21:06:56 +02:00
|
|
|
}
|
2022-10-20 23:48:13 +02:00
|
|
|
}
|
|
|
|
},
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
2023-10-27 21:06:56 +02:00
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = libraryPreferences.autoClearChapterCache(),
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_auto_clear_chapter_cache),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
2023-10-29 21:57:38 +01:00
|
|
|
|
|
|
|
@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(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_storage_usage),
|
2023-10-29 21:57:38 +01:00
|
|
|
) {
|
|
|
|
BasePreferenceWidget(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.pref_storage_usage),
|
2023-10-29 21:57:38 +01:00
|
|
|
subcomponent = {
|
|
|
|
// TODO: downloads, SD cards, bar representation?, i18n
|
|
|
|
Box(modifier = Modifier.padding(horizontal = PrefsHorizontalPadding)) {
|
|
|
|
Text(text = "Available: $available / $total (chapter cache: $chapterCacheReadableSize)")
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2022-10-15 17:38:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private data class MissingRestoreComponents(
|
|
|
|
val uri: Uri,
|
|
|
|
val sources: List<String>,
|
|
|
|
val trackers: List<String>,
|
|
|
|
)
|
|
|
|
|
2023-05-06 18:18:52 +02:00
|
|
|
private data class InvalidRestore(
|
2023-10-18 00:22:55 +02:00
|
|
|
val uri: Uri? = null,
|
2022-10-15 17:38:01 +02:00
|
|
|
val message: String,
|
|
|
|
)
|