Add unified storage location setting

Currently only using it as a replacement for the downloads location.
This commit is contained in:
arkon
2023-10-26 13:43:42 -04:00
parent e3b70ca08d
commit 695813ef7d
10 changed files with 99 additions and 106 deletions

View File

@@ -1,5 +1,6 @@
package eu.kanade.presentation.more.settings.screen
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
@@ -26,8 +27,11 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.net.toUri
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import com.hippo.unifile.UniFile
import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
@@ -49,6 +53,7 @@ import tachiyomi.core.util.lang.withUIContext
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.storage.service.StoragePreferences
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
@@ -64,15 +69,55 @@ object SettingsDataScreen : SearchableSettings {
@Composable
override fun getPreferences(): List<Preference> {
val backupPreferences = Injekt.get<BackupPreferences>()
val storagePreferences = Injekt.get<StoragePreferences>()
PermissionRequestHelper.requestStoragePermission()
return listOf(
getStorageLocationPref(storagePreferences = storagePreferences),
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
getBackupAndRestoreGroup(backupPreferences = backupPreferences),
getDataGroup(),
)
}
@Composable
private fun getStorageLocationPref(
storagePreferences: StoragePreferences,
): Preference.PreferenceItem.TextPreference {
val context = LocalContext.current
val storageDirPref = storagePreferences.baseStorageDirectory()
val storageDir by storageDirPref.collectAsState()
val pickStorageLocation = rememberLauncherForActivityResult(
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)
val file = UniFile.fromUri(context, uri)
storageDirPref.set(file.uri.toString())
}
}
return Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_storage_location),
subtitle = remember(storageDir) {
(UniFile.fromUri(context, storageDir.toUri())?.filePath)
} ?: stringResource(MR.strings.invalid_location, storageDir),
onClick = {
try {
pickStorageLocation.launch(null)
} catch (e: ActivityNotFoundException) {
context.toast(MR.strings.file_picker_error)
}
},
)
}
@Composable
private fun getBackupAndRestoreGroup(backupPreferences: BackupPreferences): Preference.PreferenceGroup {
val context = LocalContext.current

View File

@@ -1,9 +1,5 @@
package eu.kanade.presentation.more.settings.screen
import android.content.Intent
import android.os.Environment
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.collectAsState
@@ -12,10 +8,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.util.fastMap
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.presentation.category.visualName
import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
@@ -29,7 +22,6 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
object SettingsDownloadScreen : SearchableSettings {
@@ -44,7 +36,6 @@ object SettingsDownloadScreen : SearchableSettings {
val downloadPreferences = remember { Injekt.get<DownloadPreferences>() }
return listOf(
getDownloadLocationPreference(downloadPreferences = downloadPreferences),
Preference.PreferenceItem.SwitchPreference(
pref = downloadPreferences.downloadOnlyOverWifi(),
title = stringResource(MR.strings.connected_to_wifi),
@@ -70,67 +61,6 @@ object SettingsDownloadScreen : SearchableSettings {
)
}
@Composable
private fun getDownloadLocationPreference(
downloadPreferences: DownloadPreferences,
): Preference.PreferenceItem.ListPreference<String> {
val context = LocalContext.current
val currentDirPref = downloadPreferences.downloadsDirectory()
val currentDir by currentDirPref.collectAsState()
val pickLocation = rememberLauncherForActivityResult(
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)
val file = UniFile.fromUri(context, uri)
currentDirPref.set(file.uri.toString())
}
}
val defaultDirPair = rememberDefaultDownloadDir()
val customDirEntryKey = currentDir.takeIf { it != defaultDirPair.first } ?: "custom"
return Preference.PreferenceItem.ListPreference(
pref = currentDirPref,
title = stringResource(MR.strings.pref_download_directory),
subtitleProvider = { value, _ ->
remember(value) {
UniFile.fromUri(context, value.toUri())?.filePath
} ?: stringResource(MR.strings.invalid_location, value)
},
entries = mapOf(
defaultDirPair,
customDirEntryKey to stringResource(MR.strings.custom_dir),
),
onValueChanged = {
val default = it == defaultDirPair.first
if (!default) {
pickLocation.launch(null)
}
default // Don't update when non-default chosen
},
)
}
@Composable
private fun rememberDefaultDownloadDir(): Pair<String, String> {
val appName = stringResource(MR.strings.app_name)
return remember {
val file = UniFile.fromFile(
File(
"${Environment.getExternalStorageDirectory().absolutePath}${File.separator}$appName",
"downloads",
),
)!!
file.uri.toString() to file.filePath!!
}
}
@Composable
private fun getDeleteChaptersGroup(
downloadPreferences: DownloadPreferences,