2022-10-15 17:38:01 +02:00
|
|
|
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
|
2022-10-15 17:58:24 +02:00
|
|
|
import androidx.annotation.StringRes
|
2022-10-15 17:38:01 +02:00
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
import androidx.compose.runtime.ReadOnlyComposable
|
|
|
|
import androidx.compose.runtime.collectAsState
|
|
|
|
import androidx.compose.runtime.getValue
|
|
|
|
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.res.pluralStringResource
|
|
|
|
import androidx.compose.ui.res.stringResource
|
2022-10-30 17:27:12 +01:00
|
|
|
import androidx.compose.ui.util.fastMap
|
2022-10-15 17:38:01 +02:00
|
|
|
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
|
|
|
|
import eu.kanade.presentation.util.collectAsState
|
|
|
|
import eu.kanade.tachiyomi.R
|
|
|
|
import kotlinx.coroutines.runBlocking
|
2023-01-28 04:37:17 +01:00
|
|
|
import tachiyomi.domain.category.interactor.GetCategories
|
2023-01-22 16:12:29 +01:00
|
|
|
import tachiyomi.domain.category.model.Category
|
2023-03-05 18:11:47 +01:00
|
|
|
import tachiyomi.domain.download.service.DownloadPreferences
|
2022-10-15 17:38:01 +02:00
|
|
|
import uy.kohesive.injekt.Injekt
|
|
|
|
import uy.kohesive.injekt.api.get
|
|
|
|
import java.io.File
|
|
|
|
|
2022-11-23 15:14:55 +01:00
|
|
|
object SettingsDownloadScreen : SearchableSettings {
|
2022-10-15 17:58:24 +02:00
|
|
|
|
2022-10-15 17:38:01 +02:00
|
|
|
@ReadOnlyComposable
|
|
|
|
@Composable
|
2022-10-15 17:58:24 +02:00
|
|
|
@StringRes
|
|
|
|
override fun getTitleRes() = R.string.pref_category_downloads
|
2022-10-15 17:38:01 +02:00
|
|
|
|
|
|
|
@Composable
|
|
|
|
override fun getPreferences(): List<Preference> {
|
|
|
|
val getCategories = remember { Injekt.get<GetCategories>() }
|
|
|
|
val allCategories by getCategories.subscribe().collectAsState(initial = runBlocking { getCategories.await() })
|
|
|
|
|
|
|
|
val downloadPreferences = remember { Injekt.get<DownloadPreferences>() }
|
|
|
|
return listOf(
|
|
|
|
getDownloadLocationPreference(downloadPreferences = downloadPreferences),
|
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = downloadPreferences.downloadOnlyOverWifi(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.connected_to_wifi),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = downloadPreferences.saveChaptersAsCBZ(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.save_chapter_as_cbz),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
getDeleteChaptersGroup(
|
|
|
|
downloadPreferences = downloadPreferences,
|
|
|
|
categories = allCategories,
|
|
|
|
),
|
2022-10-20 23:48:13 +02:00
|
|
|
getAutoDownloadGroup(
|
2022-10-15 17:38:01 +02:00
|
|
|
downloadPreferences = downloadPreferences,
|
|
|
|
allCategories = allCategories,
|
|
|
|
),
|
|
|
|
getDownloadAheadGroup(downloadPreferences = downloadPreferences),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@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,
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_download_directory),
|
2022-10-29 15:44:12 +02:00
|
|
|
subtitleProvider = { value, _ ->
|
|
|
|
remember(value) {
|
|
|
|
UniFile.fromUri(context, value.toUri())?.filePath
|
|
|
|
} ?: stringResource(R.string.invalid_location, value)
|
|
|
|
},
|
2022-10-15 17:38:01 +02:00
|
|
|
entries = mapOf(
|
|
|
|
defaultDirPair,
|
2022-10-15 17:58:24 +02:00
|
|
|
customDirEntryKey to stringResource(R.string.custom_dir),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
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> {
|
2022-10-15 17:58:24 +02:00
|
|
|
val appName = stringResource(R.string.app_name)
|
2022-10-15 17:38:01 +02:00
|
|
|
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,
|
|
|
|
categories: List<Category>,
|
|
|
|
): Preference.PreferenceGroup {
|
|
|
|
return Preference.PreferenceGroup(
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_category_delete_chapters),
|
2022-10-15 17:38:01 +02:00
|
|
|
preferenceItems = listOf(
|
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = downloadPreferences.removeAfterMarkedAsRead(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_remove_after_marked_as_read),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
Preference.PreferenceItem.ListPreference(
|
|
|
|
pref = downloadPreferences.removeAfterReadSlots(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_remove_after_read),
|
2022-10-15 17:38:01 +02:00
|
|
|
entries = mapOf(
|
2022-10-15 17:58:24 +02:00
|
|
|
-1 to stringResource(R.string.disabled),
|
|
|
|
0 to stringResource(R.string.last_read_chapter),
|
|
|
|
1 to stringResource(R.string.second_to_last),
|
|
|
|
2 to stringResource(R.string.third_to_last),
|
|
|
|
3 to stringResource(R.string.fourth_to_last),
|
|
|
|
4 to stringResource(R.string.fifth_to_last),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = downloadPreferences.removeBookmarkedChapters(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_remove_bookmarked_chapters),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
getExcludedCategoriesPreference(
|
|
|
|
downloadPreferences = downloadPreferences,
|
|
|
|
categories = { categories },
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun getExcludedCategoriesPreference(
|
|
|
|
downloadPreferences: DownloadPreferences,
|
|
|
|
categories: () -> List<Category>,
|
|
|
|
): Preference.PreferenceItem.MultiSelectListPreference {
|
|
|
|
return Preference.PreferenceItem.MultiSelectListPreference(
|
2022-10-29 15:44:12 +02:00
|
|
|
pref = downloadPreferences.removeExcludeCategories(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_remove_exclude_categories),
|
2022-10-29 15:44:12 +02:00
|
|
|
entries = categories().associate { it.id.toString() to it.visualName },
|
2022-10-15 17:38:01 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2022-10-20 23:48:13 +02:00
|
|
|
private fun getAutoDownloadGroup(
|
2022-10-15 17:38:01 +02:00
|
|
|
downloadPreferences: DownloadPreferences,
|
|
|
|
allCategories: List<Category>,
|
|
|
|
): Preference.PreferenceGroup {
|
|
|
|
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters()
|
|
|
|
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories()
|
|
|
|
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude()
|
|
|
|
|
|
|
|
val downloadNewChapters by downloadNewChaptersPref.collectAsState()
|
|
|
|
|
|
|
|
val included by downloadNewChapterCategoriesPref.collectAsState()
|
|
|
|
val excluded by downloadNewChapterCategoriesExcludePref.collectAsState()
|
|
|
|
var showDialog by rememberSaveable { mutableStateOf(false) }
|
|
|
|
if (showDialog) {
|
|
|
|
TriStateListDialog(
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.categories),
|
|
|
|
message = stringResource(R.string.pref_download_new_categories_details),
|
2022-10-15 17:38:01 +02:00
|
|
|
items = allCategories,
|
|
|
|
initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
|
|
|
|
initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
|
|
|
|
itemLabel = { it.visualName },
|
|
|
|
onDismissRequest = { showDialog = false },
|
|
|
|
onValueChanged = { newIncluded, newExcluded ->
|
2022-10-30 17:27:12 +01:00
|
|
|
downloadNewChapterCategoriesPref.set(newIncluded.fastMap { it.id.toString() }.toSet())
|
|
|
|
downloadNewChapterCategoriesExcludePref.set(newExcluded.fastMap { it.id.toString() }.toSet())
|
2022-10-15 17:38:01 +02:00
|
|
|
showDialog = false
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return Preference.PreferenceGroup(
|
2022-10-20 23:48:13 +02:00
|
|
|
title = stringResource(R.string.pref_category_auto_download),
|
2022-10-15 17:38:01 +02:00
|
|
|
preferenceItems = listOf(
|
|
|
|
Preference.PreferenceItem.SwitchPreference(
|
|
|
|
pref = downloadNewChaptersPref,
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.pref_download_new),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
Preference.PreferenceItem.TextPreference(
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.categories),
|
2022-10-15 17:38:01 +02:00
|
|
|
subtitle = getCategoriesLabel(
|
|
|
|
allCategories = allCategories,
|
|
|
|
included = included,
|
|
|
|
excluded = excluded,
|
|
|
|
),
|
|
|
|
onClick = { showDialog = true },
|
|
|
|
enabled = downloadNewChapters,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun getDownloadAheadGroup(
|
|
|
|
downloadPreferences: DownloadPreferences,
|
|
|
|
): Preference.PreferenceGroup {
|
|
|
|
return Preference.PreferenceGroup(
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.download_ahead),
|
2022-10-15 17:38:01 +02:00
|
|
|
preferenceItems = listOf(
|
|
|
|
Preference.PreferenceItem.ListPreference(
|
|
|
|
pref = downloadPreferences.autoDownloadWhileReading(),
|
2022-10-15 17:58:24 +02:00
|
|
|
title = stringResource(R.string.auto_download_while_reading),
|
2022-10-15 17:38:01 +02:00
|
|
|
entries = listOf(0, 2, 3, 5, 10).associateWith {
|
|
|
|
if (it == 0) {
|
2022-10-15 17:58:24 +02:00
|
|
|
stringResource(R.string.disabled)
|
2022-10-15 17:38:01 +02:00
|
|
|
} else {
|
|
|
|
pluralStringResource(id = R.plurals.next_unread_chapters, count = it, it)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
2022-10-16 21:32:48 +02:00
|
|
|
Preference.PreferenceItem.InfoPreference(stringResource(R.string.download_ahead_info)),
|
2022-10-15 17:38:01 +02:00
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|