Allow excluding categories from auto-download

Closes #1412

Supersedes #4121
This commit is contained in:
arkon 2021-04-04 17:15:06 -04:00
parent 4f1275ac01
commit 0ca62a4acc
4 changed files with 61 additions and 20 deletions

View file

@ -165,6 +165,7 @@ object PreferenceKeys {
const val downloadNew = "download_new" const val downloadNew = "download_new"
const val downloadNewCategories = "download_new_categories" const val downloadNewCategories = "download_new_categories"
const val downloadNewCategoriesExclude = "download_new_categories_exclude"
const val libraryDisplayMode = "pref_display_mode_library" const val libraryDisplayMode = "pref_display_mode_library"

View file

@ -265,6 +265,7 @@ class PreferencesHelper(val context: Context) {
fun downloadNew() = flowPrefs.getBoolean(Keys.downloadNew, false) fun downloadNew() = flowPrefs.getBoolean(Keys.downloadNew, false)
fun downloadNewCategories() = flowPrefs.getStringSet(Keys.downloadNewCategories, emptySet()) fun downloadNewCategories() = flowPrefs.getStringSet(Keys.downloadNewCategories, emptySet())
fun downloadNewCategoriesExclude() = flowPrefs.getStringSet(Keys.downloadNewCategoriesExclude, emptySet())
fun lang() = prefs.getString(Keys.lang, "") fun lang() = prefs.getString(Keys.lang, "")

View file

@ -8,9 +8,9 @@ import android.os.Bundle
import android.os.Environment import android.os.Environment
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.text.buildSpannedString
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsMultiChoice
import com.afollestad.materialdialogs.list.listItemsSingleChoice import com.afollestad.materialdialogs.list.listItemsSingleChoice
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -28,6 +28,8 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateCheckBox
import eu.kanade.tachiyomi.widget.materialdialogs.listItemsQuadStateMultiChoice
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -115,18 +117,37 @@ class SettingsDownloadController : SettingsController() {
preferences.downloadNew().asImmediateFlow { isVisible = it } preferences.downloadNew().asImmediateFlow { isVisible = it }
.launchIn(viewScope) .launchIn(viewScope)
preferences.downloadNewCategories().asFlow() fun updateSummary() {
.onEach { mutableSet -> val selectedCategories = preferences.downloadNewCategories().get()
val selectedCategories = mutableSet .mapNotNull { id -> categories.find { it.id == id.toInt() } }
.mapNotNull { id -> categories.find { it.id == id.toInt() } } .sortedBy { it.order }
.sortedBy { it.order } val includedItemsText = if (selectedCategories.isEmpty()) {
context.getString(R.string.all)
summary = if (selectedCategories.isEmpty()) { } else {
resources?.getString(R.string.all) selectedCategories.joinToString { it.name }
} else {
selectedCategories.joinToString { it.name }
}
} }
val excludedCategories = preferences.downloadNewCategoriesExclude().get()
.mapNotNull { id -> categories.find { it.id == id.toInt() } }
.sortedBy { it.order }
val excludedItemsText = if (excludedCategories.isEmpty()) {
context.getString(R.string.none)
} else {
excludedCategories.joinToString { it.name }
}
summary = buildSpannedString {
append(context.getString(R.string.include, includedItemsText))
appendLine()
append(context.getString(R.string.exclude, excludedItemsText))
}
}
preferences.downloadNewCategories().asFlow()
.onEach { updateSummary() }
.launchIn(viewScope)
preferences.downloadNewCategoriesExclude().asFlow()
.onEach { updateSummary() }
.launchIn(viewScope) .launchIn(viewScope)
} }
} }
@ -210,19 +231,34 @@ class SettingsDownloadController : SettingsController() {
val items = categories.map { it.name } val items = categories.map { it.name }
val preselected = categories val preselected = categories
.filter { it.id.toString() in preferences.downloadNewCategories().get() } .map {
.map { categories.indexOf(it) } when (it.id.toString()) {
in preferences.downloadNewCategories().get() -> QuadStateCheckBox.State.CHECKED.ordinal
in preferences.downloadNewCategoriesExclude().get() -> QuadStateCheckBox.State.INVERSED.ordinal
else -> QuadStateCheckBox.State.UNCHECKED.ordinal
}
}
.toIntArray() .toIntArray()
return MaterialDialog(activity!!) return MaterialDialog(activity!!)
.title(R.string.pref_download_new_categories) .title(R.string.pref_download_new_categories)
.listItemsMultiChoice( .listItemsQuadStateMultiChoice(
items = items, items = items,
initialSelection = preselected, initialSelected = preselected
allowEmptySelection = true ) { selections ->
) { _, selections, _ -> val included = selections
val newCategories = selections.map { categories[it] } .mapIndexed { index, value -> if (value == QuadStateCheckBox.State.CHECKED.ordinal) index else null }
preferences.downloadNewCategories().set(newCategories.map { it.id.toString() }.toSet()) .filterNotNull()
.map { categories[it].id.toString() }
.toSet()
val excluded = selections
.mapIndexed { index, value -> if (value == QuadStateCheckBox.State.INVERSED.ordinal) index else null }
.filterNotNull()
.map { categories[it].id.toString() }
.toSet()
preferences.downloadNewCategories().set(included)
preferences.downloadNewCategoriesExclude().set(excluded)
} }
.positiveButton(android.R.string.ok) .positiveButton(android.R.string.ok)
.negativeButton(android.R.string.cancel) .negativeButton(android.R.string.cancel)

View file

@ -68,5 +68,8 @@ fun Manga.shouldDownloadNewChapters(db: DatabaseHelper, prefs: PreferencesHelper
.mapNotNull { it.id } .mapNotNull { it.id }
.takeUnless { it.isEmpty() } ?: listOf(0) .takeUnless { it.isEmpty() } ?: listOf(0)
val categoriesToExclude = prefs.downloadNewCategoriesExclude().get().map(String::toInt)
if (categoriesForManga.intersect(categoriesToExclude).isNotEmpty()) return false
return categoriesForManga.intersect(categoriesToDownload).isNotEmpty() return categoriesForManga.intersect(categoriesToDownload).isNotEmpty()
} }