Added search/sorting/mass enable/disable to catalouge sources
This commit is contained in:
parent
dd214f98fc
commit
5448a16b35
@ -67,6 +67,8 @@ object PreferenceKeys {
|
||||
|
||||
const val enabledLanguages = "source_languages"
|
||||
|
||||
const val sourcesSort = "sources_sort"
|
||||
|
||||
const val backupDirectory = "backup_directory"
|
||||
|
||||
const val downloadsDirectory = "download_directory"
|
||||
|
@ -98,6 +98,8 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun enabledLanguages() = rxPrefs.getStringSet(Keys.enabledLanguages, setOf("en", Locale.getDefault().language))
|
||||
|
||||
fun sourceSorting() = rxPrefs.getInteger(Keys.sourcesSort, 0)
|
||||
|
||||
fun sourceUsername(source: Source) = prefs.getString(Keys.sourceUsername(source.id), "")
|
||||
|
||||
fun sourcePassword(source: Source) = prefs.getString(Keys.sourcePassword(source.id), "")
|
||||
|
@ -1,9 +1,13 @@
|
||||
package eu.kanade.tachiyomi.ui.catalogue
|
||||
|
||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import android.view.*
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
@ -194,7 +198,7 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
|
||||
.subscribeUntilDestroy { performGlobalSearch(it.queryText().toString()) }
|
||||
}
|
||||
|
||||
fun performGlobalSearch(query: String){
|
||||
private fun performGlobalSearch(query: String){
|
||||
router.pushController(CatalogueSearchController(query).withFadeTransaction())
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ open class ExtensionController : NucleusController<ExtensionPresenter>(),
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_settings -> {
|
||||
R.id.action_filter -> {
|
||||
router.pushController((RouterTransaction.with(SettingsExtensionsController()))
|
||||
.popChangeHandler(SettingsExtensionsFadeChangeHandler())
|
||||
.pushChangeHandler(FadeChangeHandler()))
|
||||
|
@ -1,8 +1,14 @@
|
||||
package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.PreferenceGroup
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
@ -14,37 +20,47 @@ import eu.kanade.tachiyomi.widget.preference.SourceLoginDialog
|
||||
import eu.kanade.tachiyomi.widget.preference.SwitchPreferenceCategory
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.*
|
||||
import java.util.TreeMap
|
||||
|
||||
class SettingsSourcesController : SettingsController(),
|
||||
SourceLoginDialog.Listener {
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
private val onlineSources by lazy { Injekt.get<SourceManager>().getOnlineSources() }
|
||||
|
||||
private var query = ""
|
||||
|
||||
private var orderedLangs = listOf<String>()
|
||||
private var langPrefs = mutableListOf<Pair<String, SwitchPreferenceCategory>>()
|
||||
private var sourcesByLang:TreeMap<String, MutableList<HttpSource>> = TreeMap()
|
||||
private var sorting = SourcesSort.Alpha
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||
titleRes = R.string.pref_category_sources
|
||||
|
||||
sorting = SourcesSort.from(preferences.sourceSorting().getOrDefault()) ?: SourcesSort.Alpha
|
||||
activity?.invalidateOptionsMenu()
|
||||
// Get the list of active language codes.
|
||||
val activeLangsCodes = preferences.enabledLanguages().getOrDefault()
|
||||
|
||||
// Get a map of sources grouped by language.
|
||||
val sourcesByLang = onlineSources.groupByTo(TreeMap(), { it.lang })
|
||||
sourcesByLang = onlineSources.groupByTo(TreeMap(), { it.lang })
|
||||
|
||||
// Order first by active languages, then inactive ones
|
||||
val orderedLangs = sourcesByLang.keys.filter { it in activeLangsCodes } +
|
||||
sourcesByLang.keys.filterNot { it in activeLangsCodes }
|
||||
orderedLangs = sourcesByLang.keys.filter { it in activeLangsCodes } + sourcesByLang.keys
|
||||
.filterNot { it in activeLangsCodes }
|
||||
|
||||
orderedLangs.forEach { lang ->
|
||||
val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name }
|
||||
|
||||
// Create a preference group and set initial state and change listener
|
||||
SwitchPreferenceCategory(context).apply {
|
||||
langPrefs.add(Pair(lang, SwitchPreferenceCategory(context).apply {
|
||||
preferenceScreen.addPreference(this)
|
||||
title = LocaleHelper.getDisplayName(lang, context)
|
||||
isPersistent = false
|
||||
if (lang in activeLangsCodes) {
|
||||
setChecked(true)
|
||||
addLanguageSources(this, sources)
|
||||
addLanguageSources(this, sortedSources(sourcesByLang[lang]))
|
||||
}
|
||||
|
||||
onChange { newValue ->
|
||||
@ -55,11 +71,11 @@ class SettingsSourcesController : SettingsController(),
|
||||
removeAll()
|
||||
} else {
|
||||
preferences.enabledLanguages().set(current + lang)
|
||||
addLanguageSources(this, sources)
|
||||
addLanguageSources(this, sortedSources(sourcesByLang[lang]))
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +91,29 @@ class SettingsSourcesController : SettingsController(),
|
||||
private fun addLanguageSources(group: PreferenceGroup, sources: List<HttpSource>) {
|
||||
val hiddenCatalogues = preferences.hiddenCatalogues().getOrDefault()
|
||||
|
||||
val selectAllPreference = CheckBoxPreference(group.context).apply {
|
||||
|
||||
title = "\t\t${context.getString(R.string.pref_category_all_sources)}"
|
||||
key = "all_${sources.first().lang}"
|
||||
isPersistent = false
|
||||
isChecked = sources.all { it.id.toString() !in hiddenCatalogues }
|
||||
isVisible = query.isEmpty()
|
||||
|
||||
onChange { newValue ->
|
||||
val checked = newValue as Boolean
|
||||
val current = preferences.hiddenCatalogues().getOrDefault()
|
||||
if (checked)
|
||||
current.removeAll(sources.map { it.id.toString() })
|
||||
else
|
||||
current.addAll(sources.map { it.id.toString() })
|
||||
preferences.hiddenCatalogues().set(current)
|
||||
group.removeAll()
|
||||
addLanguageSources(group, sortedSources(sources))
|
||||
true
|
||||
}
|
||||
}
|
||||
group.addPreference(selectAllPreference)
|
||||
|
||||
sources.forEach { source ->
|
||||
val sourcePreference = LoginCheckBoxPreference(group.context, source).apply {
|
||||
val id = source.id.toString()
|
||||
@ -82,16 +121,19 @@ class SettingsSourcesController : SettingsController(),
|
||||
key = getSourceKey(source.id)
|
||||
isPersistent = false
|
||||
isChecked = id !in hiddenCatalogues
|
||||
isVisible = query.isEmpty() || source.name.contains(query, ignoreCase = true)
|
||||
|
||||
onChange { newValue ->
|
||||
val checked = newValue as Boolean
|
||||
val current = preferences.hiddenCatalogues().getOrDefault()
|
||||
|
||||
preferences.hiddenCatalogues().set(if (checked)
|
||||
current - id
|
||||
else
|
||||
current + id)
|
||||
preferences.hiddenCatalogues().set(
|
||||
if (checked) current - id
|
||||
else current + id
|
||||
)
|
||||
|
||||
group.removeAll()
|
||||
addLanguageSources(group, sortedSources(sources))
|
||||
true
|
||||
}
|
||||
|
||||
@ -115,4 +157,90 @@ class SettingsSourcesController : SettingsController(),
|
||||
return "source_$sourceId"
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds items to the options menu.
|
||||
*
|
||||
* @param menu menu containing options.
|
||||
* @param inflater used to load the menu xml.
|
||||
*/
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.settings_sources, menu)
|
||||
if (sorting == SourcesSort.Alpha) menu.findItem(R.id.action_sort_alpha).isChecked = true
|
||||
else menu.findItem(R.id.action_sort_enabled).isChecked = true
|
||||
|
||||
val searchItem = menu.findItem(R.id.action_search)
|
||||
val searchView = searchItem.actionView as SearchView
|
||||
searchView.maxWidth = Int.MAX_VALUE
|
||||
|
||||
if (query.isNotEmpty()) {
|
||||
searchItem.expandActionView()
|
||||
searchView.setQuery(query, true)
|
||||
searchView.clearFocus()
|
||||
}
|
||||
|
||||
searchView.queryTextChanges().filter { router.backstack.lastOrNull()?.controller() == this }
|
||||
.subscribeUntilDestroy {
|
||||
query = it.toString()
|
||||
drawSources()
|
||||
}
|
||||
|
||||
// Fixes problem with the overflow icon showing up in lieu of search
|
||||
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
||||
activity?.invalidateOptionsMenu()
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun drawSources() {
|
||||
val activeLangsCodes = preferences.enabledLanguages().getOrDefault()
|
||||
langPrefs.forEach { group ->
|
||||
if (group.first in activeLangsCodes) {
|
||||
group.second.removeAll()
|
||||
addLanguageSources(group.second, sortedSources(sourcesByLang[group.first]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sortedSources(sources: List<HttpSource>?): List<HttpSource> {
|
||||
val sourceAlpha = sources.orEmpty().sortedBy { it.name }
|
||||
return if (sorting == SourcesSort.Enabled) {
|
||||
val hiddenCatalogues = preferences.hiddenCatalogues().getOrDefault()
|
||||
sourceAlpha.filter { it.id.toString() !in hiddenCatalogues } +
|
||||
sourceAlpha.filterNot { it.id.toString() !in hiddenCatalogues }
|
||||
} else {
|
||||
sourceAlpha
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an option menu item has been selected by the user.
|
||||
*
|
||||
* @param item The selected item.
|
||||
* @return True if this event has been consumed, false if it has not.
|
||||
*/
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
sorting = when (item.itemId) {
|
||||
R.id.action_sort_alpha -> SourcesSort.Alpha
|
||||
R.id.action_sort_enabled -> SourcesSort.Enabled
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
item.isChecked = true
|
||||
preferences.sourceSorting().set(sorting.value)
|
||||
drawSources()
|
||||
return true
|
||||
}
|
||||
|
||||
enum class SourcesSort(val value: Int) {
|
||||
Alpha(0), Enabled(1);
|
||||
|
||||
companion object {
|
||||
fun from(i: Int): SourcesSort? = values().find { it.value == i }
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:id="@+id/action_filter"
|
||||
android:title="@string/action_filter"
|
||||
android:icon="@drawable/ic_filter_list_white_24dp"
|
||||
app:showAsAction="always"/>
|
||||
|
28
app/src/main/res/menu/settings_sources.xml
Normal file
28
app/src/main/res/menu/settings_sources.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_search"
|
||||
android:title="@string/action_search"
|
||||
android:icon="@drawable/ic_search_white_24dp"
|
||||
app:showAsAction="collapseActionView|ifRoom"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_sort"
|
||||
android:title="@string/action_sort"
|
||||
android:icon="@drawable/ic_sort_white_24dp"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<group android:id="@+id/group"
|
||||
android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/action_sort_alpha"
|
||||
android:title="@string/action_sort_alpha"/>
|
||||
<item
|
||||
android:id="@+id/action_sort_enabled"
|
||||
android:title="@string/action_sort_enabled"/>
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
@ -38,6 +38,7 @@
|
||||
<string name="action_filter_read">Read</string>
|
||||
<string name="action_filter_empty">Remove filter</string>
|
||||
<string name="action_sort_alpha">Alphabetically</string>
|
||||
<string name="action_sort_enabled">Enabled</string>
|
||||
<string name="action_sort_total">Total chapters</string>
|
||||
<string name="action_sort_last_read">Last read</string>
|
||||
<string name="action_sort_last_updated">Last updated</string>
|
||||
@ -116,6 +117,7 @@
|
||||
<string name="pref_category_reader">Reader</string>
|
||||
<string name="pref_category_downloads">Downloads</string>
|
||||
<string name="pref_category_sources">Sources</string>
|
||||
<string name="pref_category_all_sources">All Sources</string>
|
||||
<string name="pref_category_tracking">Tracking</string>
|
||||
<string name="pref_category_advanced">Advanced</string>
|
||||
<string name="pref_category_about">About</string>
|
||||
|
Loading…
Reference in New Issue
Block a user