Filter scanlators on delegated manga
This commit is contained in:
parent
32232c80aa
commit
e9cef78d19
@ -547,6 +547,7 @@ class MangaController :
|
|||||||
if (mainSource is MetadataSource<*, *>) {
|
if (mainSource is MetadataSource<*, *>) {
|
||||||
presenter.meta = flatMetadata.raise(mainSource.metaClass)
|
presenter.meta = flatMetadata.raise(mainSource.metaClass)
|
||||||
mangaMetaInfoAdapter?.notifyDataSetChanged()
|
mangaMetaInfoAdapter?.notifyDataSetChanged()
|
||||||
|
updateFilterIconState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
@ -4,7 +4,6 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import com.elvishew.xlog.XLog
|
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
@ -44,10 +43,13 @@ import exh.debug.DebugToggles
|
|||||||
import exh.eh.EHentaiUpdateHelper
|
import exh.eh.EHentaiUpdateHelper
|
||||||
import exh.isEhBasedSource
|
import exh.isEhBasedSource
|
||||||
import exh.md.utils.FollowStatus
|
import exh.md.utils.FollowStatus
|
||||||
|
import exh.md.utils.MdUtil
|
||||||
|
import exh.md.utils.scanlatorList
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import exh.metadata.metadata.base.FlatMetadata
|
import exh.metadata.metadata.base.FlatMetadata
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
|
import exh.metadata.metadata.base.insertFlatMetadata
|
||||||
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||||
import exh.util.asObservable
|
import exh.util.asObservable
|
||||||
import exh.util.await
|
import exh.util.await
|
||||||
@ -133,6 +135,8 @@ class MangaPresenter(
|
|||||||
private var mergedManga = emptyList<Manga>()
|
private var mergedManga = emptyList<Manga>()
|
||||||
|
|
||||||
var dedupe: Boolean = true
|
var dedupe: Boolean = true
|
||||||
|
|
||||||
|
var allChapterScanlators: Set<String> = emptySet()
|
||||||
// EXH <--
|
// EXH <--
|
||||||
|
|
||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
@ -163,7 +167,14 @@ class MangaPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.subscribeLatestCache({ view, (manga, flatMetadata) ->
|
.subscribeLatestCache({ view, (manga, flatMetadata) ->
|
||||||
if (flatMetadata != null) view.onNextMetaInfo(flatMetadata) else XLog.d("Invalid metadata")
|
flatMetadata?.let { metadata ->
|
||||||
|
view.onNextMetaInfo(metadata)
|
||||||
|
meta?.let {
|
||||||
|
it.filteredScanlators?.let {
|
||||||
|
if (chapters.isNotEmpty()) chaptersRelay.call(chapters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
view.onNextMangaInfo(manga, source)
|
view.onNextMangaInfo(manga, source)
|
||||||
})
|
})
|
||||||
@ -193,6 +204,8 @@ class MangaPresenter(
|
|||||||
// Find downloaded chapters
|
// Find downloaded chapters
|
||||||
setDownloadedChapters(chapters)
|
setDownloadedChapters(chapters)
|
||||||
|
|
||||||
|
allChapterScanlators = chapters.flatMap { it.chapter.scanlatorList() }.toSet()
|
||||||
|
|
||||||
// Store the last emission
|
// Store the last emission
|
||||||
this.chapters = chapters
|
this.chapters = chapters
|
||||||
|
|
||||||
@ -803,6 +816,15 @@ class MangaPresenter(
|
|||||||
observable = observable.filter { !it.bookmark }
|
observable = observable.filter { !it.bookmark }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
meta?.let { metadata ->
|
||||||
|
metadata.filteredScanlators?.let { filteredScanlatorString ->
|
||||||
|
val filteredScanlators = MdUtil.getScanlators(filteredScanlatorString)
|
||||||
|
observable = observable.filter { it.scanlatorList().any { group -> filteredScanlators.contains(group) } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
|
val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
|
||||||
Manga.SORTING_SOURCE -> when (sortDescending()) {
|
Manga.SORTING_SOURCE -> when (sortDescending()) {
|
||||||
true -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) }
|
true -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) }
|
||||||
@ -994,6 +1016,17 @@ class MangaPresenter(
|
|||||||
refreshChapters()
|
refreshChapters()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
fun setScanlatorFilter(filteredScanlators: Set<String>) {
|
||||||
|
val meta = meta ?: return
|
||||||
|
meta.filteredScanlators = if (filteredScanlators.size == allChapterScanlators.size) null else MdUtil.getScanlatorString(filteredScanlators)
|
||||||
|
meta.flatten().let {
|
||||||
|
db.insertFlatMetadata(it).await()
|
||||||
|
}
|
||||||
|
refreshChapters()
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the active display mode.
|
* Sets the active display mode.
|
||||||
* @param mode the mode to set.
|
* @param mode the mode to set.
|
||||||
|
@ -4,14 +4,21 @@ import android.content.Context
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
|
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.popupMenu
|
import eu.kanade.tachiyomi.util.view.popupMenu
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
||||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||||
|
import exh.md.utils.MdUtil
|
||||||
|
import exh.metadata.metadata.MangaDexSearchMetadata
|
||||||
|
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||||
|
|
||||||
class ChaptersSettingsSheet(
|
class ChaptersSettingsSheet(
|
||||||
private val router: Router,
|
private val router: Router,
|
||||||
@ -82,7 +89,7 @@ class ChaptersSettingsSheet(
|
|||||||
* Returns true if there's at least one filter from [FilterGroup] active.
|
* Returns true if there's at least one filter from [FilterGroup] active.
|
||||||
*/
|
*/
|
||||||
fun hasActiveFilters(): Boolean {
|
fun hasActiveFilters(): Boolean {
|
||||||
return filterGroup.items.any { it.state != State.IGNORE.value }
|
return filterGroup.items.any { it.state != State.IGNORE.value } || (presenter.meta?.let { it is MangaDexSearchMetadata && it.filteredScanlators != null } ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class FilterGroup : Group {
|
inner class FilterGroup : Group {
|
||||||
@ -91,8 +98,10 @@ class ChaptersSettingsSheet(
|
|||||||
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
|
private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
|
||||||
private val bookmarked = Item.TriStateGroup(R.string.action_filter_bookmarked, this)
|
private val bookmarked = Item.TriStateGroup(R.string.action_filter_bookmarked, this)
|
||||||
|
|
||||||
|
private val scanlatorFilters = Item.DrawableSelection(0, this, R.string.scanlator, R.drawable.ic_outline_people_alt_24dp)
|
||||||
|
|
||||||
override val header = null
|
override val header = null
|
||||||
override val items = listOf(downloaded, unread, bookmarked)
|
override val items = listOf(downloaded, unread, bookmarked) + if (presenter.source.getMainSource() is MetadataSource<*, *>) listOf(scanlatorFilters) else emptyList()
|
||||||
override val footer = null
|
override val footer = null
|
||||||
|
|
||||||
override fun initModels() {
|
override fun initModels() {
|
||||||
@ -107,6 +116,34 @@ class ChaptersSettingsSheet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClicked(item: Item) {
|
override fun onItemClicked(item: Item) {
|
||||||
|
if (item is Item.DrawableSelection) {
|
||||||
|
val meta = presenter.meta
|
||||||
|
if (meta == null) {
|
||||||
|
context.toast(R.string.metadata_corrupted)
|
||||||
|
return
|
||||||
|
} else if (presenter.allChapterScanlators.isEmpty()) {
|
||||||
|
context.toast(R.string.no_scanlators)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val scanlators = presenter.allChapterScanlators.toList()
|
||||||
|
val filteredScanlators = meta.filteredScanlators?.let { MdUtil.getScanlators(it) }
|
||||||
|
val preselected = if (filteredScanlators.isNullOrEmpty()) scanlators.mapIndexed { index, _ -> index }.toIntArray() else filteredScanlators.map { scanlators.indexOf(it) }.toIntArray()
|
||||||
|
|
||||||
|
MaterialDialog(context)
|
||||||
|
.title(R.string.select_scanlators)
|
||||||
|
.listItemsMultiChoice(items = presenter.allChapterScanlators.toList(), initialSelection = preselected) { _, selections, _ ->
|
||||||
|
val selected = selections.map { scanlators[it] }.toSet()
|
||||||
|
presenter.setScanlatorFilter(selected)
|
||||||
|
onGroupClicked(this)
|
||||||
|
}
|
||||||
|
.negativeButton(R.string.action_reset) {
|
||||||
|
presenter.setScanlatorFilter(presenter.allChapterScanlators)
|
||||||
|
onGroupClicked(this)
|
||||||
|
}
|
||||||
|
.positiveButton(android.R.string.ok)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
item as Item.TriStateGroup
|
item as Item.TriStateGroup
|
||||||
val newState = when (item.state) {
|
val newState = when (item.state) {
|
||||||
State.IGNORE.value -> State.INCLUDE
|
State.IGNORE.value -> State.INCLUDE
|
||||||
|
@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
|
|||||||
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.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.reader.chapter.ReaderChapterItem
|
import eu.kanade.tachiyomi.ui.reader.chapter.ReaderChapterItem
|
||||||
@ -35,6 +36,11 @@ import exh.EH_SOURCE_ID
|
|||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
import exh.md.utils.FollowStatus
|
import exh.md.utils.FollowStatus
|
||||||
|
import exh.md.utils.MdUtil
|
||||||
|
import exh.md.utils.scanlatorList
|
||||||
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
|
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||||
|
import exh.source.EnhancedHttpSource.Companion.getMainSource
|
||||||
import exh.util.awaitSingleOrNull
|
import exh.util.awaitSingleOrNull
|
||||||
import exh.util.defaultReaderType
|
import exh.util.defaultReaderType
|
||||||
import exh.util.shouldDeleteChapters
|
import exh.util.shouldDeleteChapters
|
||||||
@ -72,6 +78,11 @@ class ReaderPresenter(
|
|||||||
var manga: Manga? = null
|
var manga: Manga? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
var meta: RaisedSearchMetadata? = null
|
||||||
|
private set
|
||||||
|
// SY <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The chapter id of the currently loaded chapter. Used to restore from process kill.
|
* The chapter id of the currently loaded chapter. Used to restore from process kill.
|
||||||
*/
|
*/
|
||||||
@ -103,7 +114,11 @@ class ReaderPresenter(
|
|||||||
*/
|
*/
|
||||||
private val chapterList by lazy {
|
private val chapterList by lazy {
|
||||||
val manga = manga!!
|
val manga = manga!!
|
||||||
val dbChapters = if (manga.source == MERGED_SOURCE_ID) runBlocking { (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingleOrNull() ?: emptyList() } else db.getChapters(manga).executeAsBlocking()
|
// SY -->
|
||||||
|
val meta = meta
|
||||||
|
val filteredScanlators = MdUtil.getScanlators(meta?.filteredScanlators.orEmpty())
|
||||||
|
// SY <--
|
||||||
|
val dbChapters = /* SY --> */if (manga.source == MERGED_SOURCE_ID) runBlocking { (sourceManager.get(MERGED_SOURCE_ID) as? MergedSource)?.getChaptersFromDB(manga)?.awaitSingleOrNull() ?: emptyList() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking()
|
||||||
|
|
||||||
val selectedChapter = dbChapters.find { it.id == chapterId }
|
val selectedChapter = dbChapters.find { it.id == chapterId }
|
||||||
?: error("Requested chapter of id $chapterId not found in chapter list")
|
?: error("Requested chapter of id $chapterId not found in chapter list")
|
||||||
@ -122,7 +137,10 @@ class ReaderPresenter(
|
|||||||
manga.downloadedFilter == Manga.SHOW_DOWNLOADED &&
|
manga.downloadedFilter == Manga.SHOW_DOWNLOADED &&
|
||||||
!downloadManager.isChapterDownloaded(it, manga)
|
!downloadManager.isChapterDownloaded(it, manga)
|
||||||
) ||
|
) ||
|
||||||
(manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED && !it.bookmark)
|
(manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED && !it.bookmark) ||
|
||||||
|
// SY -->
|
||||||
|
(meta != null && it.scanlatorList().none { group -> filteredScanlators.contains(group) })
|
||||||
|
// SY <--
|
||||||
) {
|
) {
|
||||||
return@filter false
|
return@filter false
|
||||||
}
|
}
|
||||||
@ -221,7 +239,19 @@ class ReaderPresenter(
|
|||||||
db.getManga(mangaId).asRxObservable()
|
db.getManga(mangaId).asRxObservable()
|
||||||
.first()
|
.first()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnNext { init(it, initialChapterId) }
|
// SY -->
|
||||||
|
.flatMap { manga ->
|
||||||
|
val source = sourceManager.get(manga.source)?.getMainSource()
|
||||||
|
if (manga.initialized && source is MetadataSource<*, *>) {
|
||||||
|
db.getFlatMetadataForManga(mangaId).asRxSingle().map {
|
||||||
|
manga to it?.raise(source.metaClass)
|
||||||
|
}.toObservable()
|
||||||
|
} else {
|
||||||
|
Observable.just(manga to null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.doOnNext { init(it.first, initialChapterId, it.second) }
|
||||||
|
// SY <--
|
||||||
.subscribeFirst(
|
.subscribeFirst(
|
||||||
{ _, _ ->
|
{ _, _ ->
|
||||||
// Ignore onNext event
|
// Ignore onNext event
|
||||||
@ -234,10 +264,13 @@ class ReaderPresenter(
|
|||||||
* Initializes this presenter with the given [manga] and [initialChapterId]. This method will
|
* Initializes this presenter with the given [manga] and [initialChapterId]. This method will
|
||||||
* set the chapter loader, view subscriptions and trigger an initial load.
|
* set the chapter loader, view subscriptions and trigger an initial load.
|
||||||
*/
|
*/
|
||||||
private fun init(manga: Manga, initialChapterId: Long) {
|
private fun init(manga: Manga, initialChapterId: Long /* SY --> */, metadata: RaisedSearchMetadata?/* SY <-- */) {
|
||||||
if (!needsInit()) return
|
if (!needsInit()) return
|
||||||
|
|
||||||
this.manga = manga
|
this.manga = manga
|
||||||
|
// SY -->
|
||||||
|
this.meta = metadata
|
||||||
|
// SY <--
|
||||||
if (chapterId == -1L) chapterId = initialChapterId
|
if (chapterId == -1L) chapterId = initialChapterId
|
||||||
|
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package exh.md.utils
|
package exh.md.utils
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
@ -37,8 +38,7 @@ class MdUtil {
|
|||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private const
|
private const val scanlatorSeparator = " & "
|
||||||
val scanlatorSeparator = " & "
|
|
||||||
|
|
||||||
val validOneShotFinalChapters = listOf("0", "1")
|
val validOneShotFinalChapters = listOf("0", "1")
|
||||||
|
|
||||||
@ -276,3 +276,9 @@ private fun getMDUrlWithoutDomain(orig: String): String {
|
|||||||
orig
|
orig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Chapter.scanlatorList(): List<String> {
|
||||||
|
return this.scanlator?.let {
|
||||||
|
MdUtil.getScanlators(it)
|
||||||
|
} ?: listOf("No scanlator")
|
||||||
|
}
|
||||||
|
@ -46,6 +46,8 @@ abstract class RaisedSearchMetadata {
|
|||||||
@Transient
|
@Transient
|
||||||
val titles = mutableListOf<RaisedTitle>()
|
val titles = mutableListOf<RaisedTitle>()
|
||||||
|
|
||||||
|
var filteredScanlators: String? = null
|
||||||
|
|
||||||
fun getTitleOfType(type: Int): String? = titles.find { it.type == type }?.title
|
fun getTitleOfType(type: Int): String? = titles.find { it.type == type }?.title
|
||||||
|
|
||||||
fun replaceTitleOfType(type: Int, newTitle: String?) {
|
fun replaceTitleOfType(type: Int, newTitle: String?) {
|
||||||
|
@ -567,4 +567,10 @@
|
|||||||
<string name="mangadex_push_favorites_to_mangadex_summary">Syncs any non MdList tracked manga to MangaDex as reading.</string>
|
<string name="mangadex_push_favorites_to_mangadex_summary">Syncs any non MdList tracked manga to MangaDex as reading.</string>
|
||||||
<string name="mangadex_push_favorites_to_mangadex_toast">Pushed %d manga to MangaDex</string>
|
<string name="mangadex_push_favorites_to_mangadex_toast">Pushed %d manga to MangaDex</string>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Scanlator filters -->
|
||||||
|
<string name="select_scanlators">Scanlator groups to show</string>
|
||||||
|
<string name="metadata_corrupted">Metadata corrupted, please refresh the manga</string>
|
||||||
|
<string name="no_scanlators">No scanlators available</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user