Ability to order sources by library count when migrating (#6000)

* order sources by library count when migrating (closes #4703)

* Use plain menu instead of full-on sheet
This commit is contained in:
Andreas 2021-10-01 23:37:43 +02:00 committed by GitHub
parent c6d4e4c15f
commit ba8abd94a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 118 additions and 2 deletions

View File

@ -151,6 +151,9 @@ object PreferenceKeys {
const val librarySortingMode = "library_sorting_mode" const val librarySortingMode = "library_sorting_mode"
const val librarySortingDirection = "library_sorting_ascending" const val librarySortingDirection = "library_sorting_ascending"
const val migrationSortingMode = "pref_migration_sorting"
const val migrationSortingDirection = "pref_migration_direction"
const val automaticExtUpdates = "automatic_ext_updates" const val automaticExtUpdates = "automatic_ext_updates"
const val showNsfwSource = "show_nsfw_source" const val showNsfwSource = "show_nsfw_source"

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferenceValues.ThemeMode.system import eu.kanade.tachiyomi.data.preference.PreferenceValues.ThemeMode.system
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.anilist.Anilist import eu.kanade.tachiyomi.data.track.anilist.Anilist
import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrationSourcesController
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
@ -267,6 +268,9 @@ class PreferencesHelper(val context: Context) {
fun librarySortingMode() = flowPrefs.getEnum(Keys.librarySortingMode, SortModeSetting.ALPHABETICAL) fun librarySortingMode() = flowPrefs.getEnum(Keys.librarySortingMode, SortModeSetting.ALPHABETICAL)
fun librarySortingAscending() = flowPrefs.getEnum(Keys.librarySortingDirection, SortDirectionSetting.ASCENDING) fun librarySortingAscending() = flowPrefs.getEnum(Keys.librarySortingDirection, SortDirectionSetting.ASCENDING)
fun migrationSortingMode() = flowPrefs.getEnum(Keys.migrationSortingMode, MigrationSourcesController.SortSetting.ALPHABETICAL)
fun migrationSortingDirection() = flowPrefs.getEnum(Keys.migrationSortingDirection, MigrationSourcesController.DirectionSetting.ASCENDING)
fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true) fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
fun showNsfwSource() = flowPrefs.getBoolean(Keys.showNsfwSource, true) fun showNsfwSource() = flowPrefs.getBoolean(Keys.showNsfwSource, true)

View File

@ -9,16 +9,20 @@ import androidx.recyclerview.widget.LinearLayoutManager
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.MigrationSourcesControllerBinding import eu.kanade.tachiyomi.databinding.MigrationSourcesControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaController import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaController
import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.openInBrowser
import uy.kohesive.injekt.injectLazy
class MigrationSourcesController : class MigrationSourcesController :
NucleusController<MigrationSourcesControllerBinding, MigrationSourcesPresenter>(), NucleusController<MigrationSourcesControllerBinding, MigrationSourcesPresenter>(),
FlexibleAdapter.OnItemClickListener { FlexibleAdapter.OnItemClickListener {
private val preferences: PreferencesHelper by injectLazy()
private var adapter: SourceAdapter? = null private var adapter: SourceAdapter? = null
init { init {
@ -56,12 +60,31 @@ class MigrationSourcesController :
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (val itemId = item.itemId) {
R.id.action_source_migration_help -> activity?.openInBrowser(HELP_URL) R.id.action_source_migration_help -> activity?.openInBrowser(HELP_URL)
R.id.asc_alphabetical, R.id.desc_alphabetical -> {
setSortingDirection(SortSetting.ALPHABETICAL, itemId == R.id.asc_alphabetical)
}
R.id.asc_count, R.id.desc_count -> {
setSortingDirection(SortSetting.TOTAL, itemId == R.id.asc_count)
}
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
private fun setSortingDirection(sortSetting: SortSetting, isAscending: Boolean) {
val direction = if (isAscending) {
DirectionSetting.ASCENDING
} else {
DirectionSetting.DESCENDING
}
preferences.migrationSortingDirection().set(direction)
preferences.migrationSortingMode().set(sortSetting)
presenter.requestSortUpdate()
}
fun setSources(sourcesWithManga: List<SourceItem>) { fun setSources(sourcesWithManga: List<SourceItem>) {
// Show empty view if needed // Show empty view if needed
if (sourcesWithManga.isNotEmpty()) { if (sourcesWithManga.isNotEmpty()) {
@ -79,6 +102,16 @@ class MigrationSourcesController :
parentController!!.router.pushController(controller.withFadeTransaction()) parentController!!.router.pushController(controller.withFadeTransaction())
return false return false
} }
enum class DirectionSetting {
ASCENDING,
DESCENDING;
}
enum class SortSetting {
ALPHABETICAL,
TOTAL;
}
} }
private const val HELP_URL = "https://tachiyomi.org/help/guides/source-migration/" private const val HELP_URL = "https://tachiyomi.org/help/guides/source-migration/"

View File

@ -1,25 +1,38 @@
package eu.kanade.tachiyomi.ui.browse.migration.sources package eu.kanade.tachiyomi.ui.browse.migration.sources
import android.os.Bundle import android.os.Bundle
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.combineLatest
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.text.Collator
import java.util.Collections
import java.util.Locale
class MigrationSourcesPresenter( class MigrationSourcesPresenter(
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),
private val db: DatabaseHelper = Injekt.get() private val db: DatabaseHelper = Injekt.get()
) : BasePresenter<MigrationSourcesController>() { ) : BasePresenter<MigrationSourcesController>() {
private val preferences: PreferencesHelper by injectLazy()
private val sortRelay = BehaviorRelay.create(Unit)
override fun onCreate(savedState: Bundle?) { override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState) super.onCreate(savedState)
db.getFavoriteMangas() db.getFavoriteMangas()
.asRxObservable() .asRxObservable()
.combineLatest(sortRelay.observeOn(Schedulers.io())) { sources, _ -> sources }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.map { findSourcesWithManga(it) } .map { findSourcesWithManga(it) }
.subscribeLatestCache(MigrationSourcesController::setSources) .subscribeLatestCache(MigrationSourcesController::setSources)
@ -34,7 +47,36 @@ class MigrationSourcesPresenter(
val source = sourceManager.getOrStub(it.key) val source = sourceManager.getOrStub(it.key)
SourceItem(source, it.value.size, header) SourceItem(source, it.value.size, header)
} }
.sortedBy { it.source.name.lowercase() } .sortedWith(sortFn())
.toList() .toList()
} }
fun sortFn(): java.util.Comparator<SourceItem> {
val sort by lazy {
preferences.migrationSortingMode().get()
}
val direction by lazy {
preferences.migrationSortingDirection().get()
}
val locale = Locale.getDefault()
val collator = Collator.getInstance(locale).apply {
strength = Collator.PRIMARY
}
val sortFn: (SourceItem, SourceItem) -> Int = { a, b ->
when (sort) {
MigrationSourcesController.SortSetting.ALPHABETICAL -> collator.compare(a.source.name.lowercase(locale), b.source.name.lowercase(locale))
MigrationSourcesController.SortSetting.TOTAL -> a.mangaCount.compareTo(b.mangaCount)
}
}
return when (direction) {
MigrationSourcesController.DirectionSetting.ASCENDING -> Comparator(sortFn)
MigrationSourcesController.DirectionSetting.DESCENDING -> Collections.reverseOrder(sortFn)
}
}
fun requestSortUpdate() {
sortRelay.call(Unit)
}
} }

View File

@ -7,5 +7,38 @@
android:title="@string/migration_help_guide" android:title="@string/migration_help_guide"
app:iconTint="?attr/colorOnToolbar" app:iconTint="?attr/colorOnToolbar"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/action_sort"
android:title="@string/action_sort"
app:showAsAction="never">
<menu>
<item
android:id="@+id/action_sort_alphabetical"
android:title="@string/action_sort_alpha"
app:showAsAction="never">
<menu>
<item
android:id="@+id/asc_alphabetical"
android:title="@string/action_asc" />
<item
android:id="@+id/desc_alphabetical"
android:title="@string/action_desc" />
</menu>
</item>
<item
android:id="@+id/action_sort_count"
android:title="@string/action_sort_count"
app:showAsAction="never">
<menu>
<item
android:id="@+id/asc_count"
android:title="@string/action_asc" />
<item
android:id="@+id/desc_count"
android:title="@string/action_desc" />
</menu>
</item>
</menu>
</item>
</menu> </menu>

View File

@ -39,6 +39,7 @@
<string name="action_filter_unread">Unread</string> <string name="action_filter_unread">Unread</string>
<string name="action_filter_empty">Remove filter</string> <string name="action_filter_empty">Remove filter</string>
<string name="action_sort_alpha">Alphabetically</string> <string name="action_sort_alpha">Alphabetically</string>
<string name="action_sort_count">Total manga</string>
<string name="action_sort_total">Total chapters</string> <string name="action_sort_total">Total chapters</string>
<string name="action_sort_last_read">Last read</string> <string name="action_sort_last_read">Last read</string>
<string name="action_sort_last_checked">Last checked</string> <string name="action_sort_last_checked">Last checked</string>