From 71ab6d38e45b8539050c2882e0e7a399c333c548 Mon Sep 17 00:00:00 2001 From: len Date: Sun, 15 Jan 2017 17:04:31 +0100 Subject: [PATCH] Complete group filters --- .../data/source/online/english/Batoto.kt | 32 +++++--- .../data/source/online/english/Kissmanga.kt | 16 ++-- .../data/source/online/english/Mangafox.kt | 8 +- .../data/source/online/english/Mangahere.kt | 14 ++-- .../data/source/online/english/Mangasee.kt | 80 ++++++++++--------- .../source/online/english/Readmangatoday.kt | 22 +++-- .../ui/catalogue/CatalogueFragment.kt | 6 +- .../ui/catalogue/CatalogueNavigationView.kt | 50 ++---------- .../ui/catalogue/CataloguePresenter.kt | 47 +++++++++++ .../ui/catalogue/filter/GroupItem.kt | 2 +- .../ui/catalogue/filter/SectionItems.kt | 48 +++++++++++ .../ui/catalogue/filter/SortGroup.kt | 19 +---- .../tachiyomi/ui/catalogue/filter/SortItem.kt | 5 +- .../tachiyomi/ui/category/CategoryActivity.kt | 2 +- .../main/res/layout/navigation_view_sort.xml | 30 ------- .../res/layout/navigation_view_sort_item.xml | 21 ----- .../main/res/layout/navigation_view_text.xml | 2 +- app/src/main/res/values/ids.xml | 6 ++ 18 files changed, 217 insertions(+), 193 deletions(-) delete mode 100644 app/src/main/res/layout/navigation_view_sort.xml delete mode 100644 app/src/main/res/layout/navigation_view_sort_item.xml create mode 100644 app/src/main/res/values/ids.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.kt index ab8d4e539f..e695b2c289 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Batoto.kt @@ -93,8 +93,18 @@ class Batoto : ParsedOnlineSource(), LoginSource { is Status -> if (!filter.isIgnored()) { url.addQueryParameter("completed", if (filter.isExcluded()) "i" else "c") } - is Genre -> if (!filter.isIgnored()) { - genres += (if (filter.isExcluded()) ";e" else ";i") + filter.id + is GenreList -> { + filter.state.forEach { filter -> + when (filter) { + is Genre -> if (!filter.isIgnored()) { + genres += (if (filter.isExcluded()) ";e" else ";i") + filter.id + } + is SelectField -> { + val sel = filter.values[filter.state].value + if (!sel.isEmpty()) url.addQueryParameter(filter.key, sel) + } + } + } } is TextField -> { if (!filter.state.isEmpty()) url.addQueryParameter(filter.key, filter.state) @@ -292,23 +302,25 @@ class Batoto : ParsedOnlineSource(), LoginSource { private class TextField(name: String, val key: String) : Filter.Text(name) private class SelectField(name: String, val key: String, values: Array, state: Int = 0) : Filter.Select(name, values, state) private class Flag(name: String, val key: String, val valTrue: String, val valFalse: String) : Filter.CheckBox(name) - private class OrderBy() : Filter.Sort("Order by", + private class GenreList(genres: List>) : Filter.Group>("Genres", genres) + private class OrderBy : Filter.Sort("Order by", arrayOf("Title", "Author", "Artist", "Rating", "Views", "Last Update"), Filter.Sort.Selection(4, false)) - // [...document.querySelectorAll("#advanced_options div.genre_buttons")].map((el,i) => { - // const onClick=el.getAttribute('onclick');const id=onClick.substr(14,onClick.length-16);return `Genre("${el.textContent.trim()}", ${id})` - // }).join(',\n') - // on https://bato.to/search override fun getFilterList() = FilterList( TextField("Author", "artist_name"), SelectField("Type", "type", arrayOf(ListValue("Any", ""), ListValue("Manga (Jp)", "jp"), ListValue("Manhwa (Kr)", "kr"), ListValue("Manhua (Cn)", "cn"), ListValue("Artbook", "ar"), ListValue("Other", "ot"))), Status(), Flag("Exclude mature", "mature", "m", ""), - Filter.Separator(), OrderBy(), - Filter.Separator(), - Filter.Header("Genres"), + GenreList(getGenreList()) + ) + + // [...document.querySelectorAll("#advanced_options div.genre_buttons")].map((el,i) => { + // const onClick=el.getAttribute('onclick');const id=onClick.substr(14,onClick.length-16);return `Genre("${el.textContent.trim()}", ${id})` + // }).join(',\n') + // on https://bato.to/search + private fun getGenreList() = listOf( SelectField("Inclusion mode", "genre_cond", arrayOf(ListValue("And (all selected genres)", "and"), ListValue("Or (any selected genres) ", "or"))), Genre("4-Koma", 40), Genre("Action", 1), diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.kt index be38bc53a9..4e3d3ea8b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Kissmanga.kt @@ -64,7 +64,7 @@ class Kissmanga : ParsedOnlineSource() { when (filter) { is Author -> add("authorArtist", filter.state) is Status -> add("status", arrayOf("", "Completed", "Ongoing")[filter.state]) - is Genre -> add("genres", filter.state.toString()) + is GenreList -> filter.state.forEach { genre -> add("genres", genre.state.toString()) } } } } @@ -134,16 +134,20 @@ class Kissmanga : ParsedOnlineSource() { override fun imageUrlParse(document: Document) = "" - private class Status() : Filter.TriState("Completed") - private class Author() : Filter.Text("Author") + private class Status : Filter.TriState("Completed") + private class Author : Filter.Text("Author") private class Genre(name: String) : Filter.TriState(name) + private class GenreList(genres: List) : Filter.Group("Genres", genres) - // $("select[name=\"genres\"]").map((i,el) => `Genre("${$(el).next().text().trim()}", ${i})`).get().join(',\n') - // on http://kissmanga.com/AdvanceSearch override fun getFilterList() = FilterList( Author(), Status(), - Filter.Header("Genres"), + GenreList(getGenreList()) + ) + + // $("select[name=\"genres\"]").map((i,el) => `Genre("${$(el).next().text().trim()}", ${i})`).get().join(',\n') + // on http://kissmanga.com/AdvanceSearch + private fun getGenreList() = listOf( Genre("4-Koma"), Genre("Action"), Genre("Adult"), diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.kt index 3b3add67aa..800abd1c59 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangafox.kt @@ -59,11 +59,7 @@ class Mangafox : ParsedOnlineSource() { (if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> when (filter) { is Status -> url.addQueryParameter(filter.id, filter.state.toString()) - is GenreList -> { - filter.state.forEach { genre -> - url.addQueryParameter(genre.id, genre.state.toString()) - } - } + is GenreList -> filter.state.forEach { genre -> url.addQueryParameter(genre.id, genre.state.toString()) } is TextField -> url.addQueryParameter(filter.key, filter.state) is Type -> url.addQueryParameter("type", if(filter.state == 0) "" else filter.state.toString()) is OrderBy -> { @@ -180,9 +176,7 @@ class Mangafox : ParsedOnlineSource() { TextField("Artist", "artist"), Type(), Status(), - Filter.Separator(), OrderBy(), - Filter.Separator(), GenreList(getGenreList()) ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.kt index 1dfb308fc7..5ea7246264 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangahere.kt @@ -61,7 +61,7 @@ class Mangahere : ParsedOnlineSource() { (if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> when (filter) { is Status -> url.addQueryParameter("is_completed", arrayOf("", "1", "0")[filter.state]) - is Genre -> url.addQueryParameter(filter.id, filter.state.toString()) + is GenreList -> filter.state.forEach { genre -> url.addQueryParameter(genre.id, genre.state.toString()) } is TextField -> url.addQueryParameter(filter.key, filter.state) is Type -> url.addQueryParameter("direction", arrayOf("", "rl", "lr")[filter.state]) is OrderBy -> { @@ -169,18 +169,20 @@ class Mangahere : ParsedOnlineSource() { private class OrderBy : Filter.Sort("Order by", arrayOf("Series name", "Rating", "Views", "Total chapters", "Last chapter"), Filter.Sort.Selection(2, false)) + private class GenreList(genres: List) : Filter.Group("Genres", genres) - // [...document.querySelectorAll("select[id^='genres'")].map((el,i) => `Genre("${el.nextSibling.nextSibling.textContent.trim()}", "${el.getAttribute('name')}")`).join(',\n') - // http://www.mangahere.co/advsearch.htm override fun getFilterList() = FilterList( TextField("Author", "author"), TextField("Artist", "artist"), Type(), Status(), - Filter.Separator(), OrderBy(), - Filter.Separator(), - Filter.Header("Genres"), + GenreList(getGenreList()) + ) + + // [...document.querySelectorAll("select[id^='genres'")].map((el,i) => `Genre("${el.nextSibling.nextSibling.textContent.trim()}", "${el.getAttribute('name')}")`).join(',\n') + // http://www.mangahere.co/advsearch.htm + private fun getGenreList() = listOf( Genre("Action"), Genre("Adventure"), Genre("Comedy"), diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt index b85f20dd6c..9f9f3cd575 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt @@ -50,8 +50,8 @@ class Mangasee : ParsedOnlineSource() { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { val url = HttpUrl.parse("$baseUrl/search/request.php").newBuilder() if (!query.isEmpty()) url.addQueryParameter("keyword", query) - var genres: String? = null - var genresNo: String? = null + val genres = mutableListOf() + val genresNo = mutableListOf() for (filter in if (filters.isEmpty()) getFilterList() else filters) { when (filter) { is Sort -> { @@ -62,14 +62,16 @@ class Mangasee : ParsedOnlineSource() { } is SelectField -> if (filter.state != 0) url.addQueryParameter(filter.key, filter.values[filter.state]) is TextField -> if (!filter.state.isEmpty()) url.addQueryParameter(filter.key, filter.state) - is Genre -> when (filter.state) { - Filter.TriState.STATE_INCLUDE -> genres = if (genres == null) filter.name else genres + "," + filter.name - Filter.TriState.STATE_EXCLUDE -> genresNo = if (genresNo == null) filter.name else genresNo + "," + filter.name + is GenreList -> filter.state.forEach { genre -> + when (genre.state) { + Filter.TriState.STATE_INCLUDE -> genres.add(genre.name) + Filter.TriState.STATE_EXCLUDE -> genresNo.add(genre.name) + } } } } - if (genres != null) url.addQueryParameter("genre", genres) - if (genresNo != null) url.addQueryParameter("genreNo", genresNo) + if (genres.isNotEmpty()) url.addQueryParameter("genre", genres.joinToString(",")) + if (genresNo.isNotEmpty()) url.addQueryParameter("genreNo", genresNo.joinToString(",")) val (body, requestUrl) = convertQueryToPost(page, url.toString()) return POST(requestUrl, headers, body.build()) @@ -155,23 +157,51 @@ class Mangasee : ParsedOnlineSource() { override fun imageUrlParse(document: Document): String = document.select("img.CurImage").attr("src") + override fun latestUpdatesNextPageSelector() = "button.requestMore" + + override fun latestUpdatesSelector(): String = "a.latestSeries" + + override fun latestUpdatesRequest(page: Int): Request { + val url = "http://mangaseeonline.net/home/latest.request.php" + val (body, requestUrl) = convertQueryToPost(page, url) + return POST(requestUrl, headers, body.build()) + } + + override fun latestUpdatesFromElement(element: Element): SManga { + val manga = SManga.create() + element.select("a.latestSeries").first().let { + val chapterUrl = it.attr("href") + val indexOfMangaUrl = chapterUrl.indexOf("-chapter-") + val indexOfLastPath = chapterUrl.lastIndexOf("/") + val mangaUrl = chapterUrl.substring(indexOfLastPath, indexOfMangaUrl) + val defaultText = it.select("p.clamp2").text() + val m = recentUpdatesPattern.matcher(defaultText) + val title = if (m.matches()) m.group(1) else defaultText + manga.setUrlWithoutDomain("/manga" + mangaUrl) + manga.title = title + } + return manga + } + private class Sort : Filter.Sort("Sort", arrayOf("Alphabetically", "Date updated", "Popularity"), Filter.Sort.Selection(2, false)) private class Genre(name: String) : Filter.TriState(name) private class TextField(name: String, val key: String) : Filter.Text(name) private class SelectField(name: String, val key: String, values: Array, state: Int = 0) : Filter.Select(name, values, state) + private class GenreList(genres: List) : Filter.Group("Genres", genres) - // [...document.querySelectorAll("label.triStateCheckBox input")].map(el => `Filter("${el.getAttribute('name')}", "${el.nextSibling.textContent.trim()}")`).join(',\n') - // http://mangasee.co/advanced-search/ override fun getFilterList() = FilterList( TextField("Years", "year"), TextField("Author", "author"), SelectField("Scan Status", "status", arrayOf("Any", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing")), SelectField("Publish Status", "pstatus", arrayOf("Any", "Cancelled", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing", "Unfinished")), SelectField("Type", "type", arrayOf("Any", "Doujinshi", "Manga", "Manhua", "Manhwa", "OEL", "One-shot")), - Filter.Separator(), Sort(), - Filter.Separator(), - Filter.Header("Genres"), + GenreList(getGenreList()) + ) + + // [...document.querySelectorAll("label.triStateCheckBox input")].map(el => `Filter("${el.getAttribute('name')}", "${el.nextSibling.textContent.trim()}")`).join(',\n') + // http://mangasee.co/advanced-search/ + private fun getGenreList() = listOf( Genre("Action"), Genre("Adult"), Genre("Adventure"), @@ -210,30 +240,4 @@ class Mangasee : ParsedOnlineSource() { Genre("Yuri") ) - override fun latestUpdatesNextPageSelector() = "button.requestMore" - - override fun latestUpdatesSelector(): String = "a.latestSeries" - - override fun latestUpdatesRequest(page: Int): Request { - val url = "http://mangaseeonline.net/home/latest.request.php" - val (body, requestUrl) = convertQueryToPost(page, url) - return POST(requestUrl, headers, body.build()) - } - - override fun latestUpdatesFromElement(element: Element): SManga { - val manga = SManga.create() - element.select("a.latestSeries").first().let { - val chapterUrl = it.attr("href") - val indexOfMangaUrl = chapterUrl.indexOf("-chapter-") - val indexOfLastPath = chapterUrl.lastIndexOf("/") - val mangaUrl = chapterUrl.substring(indexOfLastPath, indexOfMangaUrl) - val defaultText = it.select("p.clamp2").text() - val m = recentUpdatesPattern.matcher(defaultText) - val title = if (m.matches()) m.group(1) else defaultText - manga.setUrlWithoutDomain("/manga" + mangaUrl) - manga.title = title - } - return manga - } - } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Readmangatoday.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Readmangatoday.kt index 7175b3aa9e..daef7561de 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Readmangatoday.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Readmangatoday.kt @@ -70,9 +70,11 @@ class Readmangatoday : ParsedOnlineSource() { is TextField -> builder.add(filter.key, filter.state) is Type -> builder.add("type", arrayOf("all", "japanese", "korean", "chinese")[filter.state]) is Status -> builder.add("status", arrayOf("both", "completed", "ongoing")[filter.state]) - is Genre -> when (filter.state) { - Filter.TriState.STATE_INCLUDE -> builder.add("include[]", filter.id.toString()) - Filter.TriState.STATE_EXCLUDE -> builder.add("exclude[]", filter.id.toString()) + is GenreList -> filter.state.forEach { genre -> + when (genre.state) { + Filter.TriState.STATE_INCLUDE -> builder.add("include[]", genre.id.toString()) + Filter.TriState.STATE_EXCLUDE -> builder.add("exclude[]", genre.id.toString()) + } } } } @@ -161,19 +163,23 @@ class Readmangatoday : ParsedOnlineSource() { override fun imageUrlParse(document: Document) = document.select("img.img-responsive-2").first().attr("src") - private class Status() : Filter.TriState("Completed") + private class Status : Filter.TriState("Completed") private class Genre(name: String, val id: Int) : Filter.TriState(name) private class TextField(name: String, val key: String) : Filter.Text(name) - private class Type() : Filter.Select("Type", arrayOf("All", "Japanese Manga", "Korean Manhwa", "Chinese Manhua")) + private class Type : Filter.Select("Type", arrayOf("All", "Japanese Manga", "Korean Manhwa", "Chinese Manhua")) + private class GenreList(genres: List) : Filter.Group("Genres", genres) - // [...document.querySelectorAll("ul.manga-cat span")].map(el => `Genre("${el.nextSibling.textContent.trim()}", ${el.getAttribute('data-id')})`).join(',\n') - // http://www.readmanga.today/advanced-search override fun getFilterList() = FilterList( TextField("Author", "author-name"), TextField("Artist", "artist-name"), Type(), Status(), - Filter.Header("Genres"), + GenreList(getGenreList()) + ) + + // [...document.querySelectorAll("ul.manga-cat span")].map(el => `Genre("${el.nextSibling.textContent.trim()}", ${el.getAttribute('data-id')})`).join(',\n') + // http://www.readmanga.today/advanced-search + private fun getGenreList() = listOf( Genre("Action", 2), Genre("Adventure", 4), Genre("Comedy", 5), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt index 36228ec07f..6283ced899 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt @@ -208,7 +208,7 @@ open class CatalogueFragment : BaseRxFragment(), FlexibleVie showProgressBar() adapter.clear() presenter.setActiveSource(source) - navView?.setFilters(presenter.sourceFilters) + navView?.setFilters(presenter.filterItems) activity.invalidateOptionsMenu() } } @@ -229,7 +229,7 @@ open class CatalogueFragment : BaseRxFragment(), FlexibleVie this.navView = navView activity.drawer.addView(navView) activity.drawer.addDrawerListener(drawerListener) - navView.setFilters(presenter.sourceFilters) + navView.setFilters(presenter.filterItems) navView.post { if (isAdded && !activity.drawer.isDrawerOpen(navView)) @@ -247,7 +247,7 @@ open class CatalogueFragment : BaseRxFragment(), FlexibleVie presenter.appliedFilters = FilterList() val newFilters = presenter.source.getFilterList() presenter.sourceFilters = newFilters - navView.setFilters(newFilters) + navView.setFilters(presenter.filterItems) } showProgressBar() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueNavigationView.kt index 2677cce3ab..1bf4d3c0ff 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueNavigationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueNavigationView.kt @@ -5,11 +5,7 @@ import android.util.AttributeSet import android.view.ViewGroup import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible -import eu.davidea.flexibleadapter.items.ISectionable import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.source.model.Filter -import eu.kanade.tachiyomi.data.source.model.FilterList -import eu.kanade.tachiyomi.ui.catalogue.filter.* import eu.kanade.tachiyomi.util.inflate import eu.kanade.tachiyomi.widget.SimpleNavigationView import kotlinx.android.synthetic.main.catalogue_drawer_content.view.* @@ -18,7 +14,9 @@ import kotlinx.android.synthetic.main.catalogue_drawer_content.view.* class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : SimpleNavigationView(context, attrs) { - val adapter = FlexibleAdapter>(null) + val adapter: FlexibleAdapter> = FlexibleAdapter>(null) + .setDisplayHeadersAtStartUp(true) + .setStickyHeaders(true) var onSearchClicked = {} @@ -26,53 +24,17 @@ class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs: init { recycler.adapter = adapter + recycler.setHasFixedSize(true) val view = inflate(R.layout.catalogue_drawer_content) ((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler) addView(view) search_btn.setOnClickListener { onSearchClicked() } reset_btn.setOnClickListener { onResetClicked() } - - adapter.setDisplayHeadersAtStartUp(true) - adapter.setStickyHeaders(true) } - fun setFilters(filters: FilterList) { - val items = filters.mapNotNull { - when (it) { - is Filter.Header -> HeaderItem(it) - is Filter.Separator -> SeparatorItem(it) - is Filter.CheckBox -> CheckboxItem(it) - is Filter.TriState -> TriStateItem(it) - is Filter.Text -> TextItem(it) - is Filter.Select<*> -> SelectItem(it) - is Filter.Group<*> -> { - val group = GroupItem(it) - val subItems = it.state.mapNotNull { - when (it) { - is Filter.CheckBox -> CheckboxSectionItem(it) - is Filter.TriState -> TriStateSectionItem(it) - is Filter.Text -> TextSectionItem(it) - is Filter.Select<*> -> SelectSectionItem(it) - else -> null - } as? ISectionable<*, *> - } - subItems.forEach { it.header = group } - group.subItems = subItems - group - } - is Filter.Sort -> { - val group = SortGroup(it) - val subItems = it.values.mapNotNull { - SortItem(it, group) - } - group.subItems = subItems - group - } - else -> null - } - } - adapter.updateDataSet(items) + fun setFilters(items: List>) { + adapter.updateDataSet(items.toMutableList()) } } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt index 296728e5cf..e796a048e3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt @@ -1,6 +1,8 @@ package eu.kanade.tachiyomi.ui.catalogue import android.os.Bundle +import eu.davidea.flexibleadapter.items.IFlexible +import eu.davidea.flexibleadapter.items.ISectionable import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga @@ -9,10 +11,12 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.source.CatalogueSource import eu.kanade.tachiyomi.data.source.Source import eu.kanade.tachiyomi.data.source.SourceManager +import eu.kanade.tachiyomi.data.source.model.Filter import eu.kanade.tachiyomi.data.source.model.FilterList import eu.kanade.tachiyomi.data.source.model.SManga import eu.kanade.tachiyomi.data.source.online.LoginSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.catalogue.filter.* import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -68,6 +72,12 @@ open class CataloguePresenter : BasePresenter() { * Modifiable list of filters. */ var sourceFilters = FilterList() + set(value) { + field = value + filterItems = value.toItems() + } + + var filterItems: List> = emptyList() /** * List of filters used by the [Pager]. If empty alongside [query], the popular query is used. @@ -362,4 +372,41 @@ open class CataloguePresenter : BasePresenter() { return CataloguePager(source, query, filters) } + private fun FilterList.toItems(): List> { + return mapNotNull { + when (it) { + is Filter.Header -> HeaderItem(it) + is Filter.Separator -> SeparatorItem(it) + is Filter.CheckBox -> CheckboxItem(it) + is Filter.TriState -> TriStateItem(it) + is Filter.Text -> TextItem(it) + is Filter.Select<*> -> SelectItem(it) + is Filter.Group<*> -> { + val group = GroupItem(it) + val subItems = it.state.mapNotNull { + when (it) { + is Filter.CheckBox -> CheckboxSectionItem(it) + is Filter.TriState -> TriStateSectionItem(it) + is Filter.Text -> TextSectionItem(it) + is Filter.Select<*> -> SelectSectionItem(it) + else -> null + } as? ISectionable<*, *> + } + subItems.forEach { it.header = group } + group.subItems = subItems + group + } + is Filter.Sort -> { + val group = SortGroup(it) + val subItems = it.values.mapNotNull { + SortItem(it, group) + } + group.subItems = subItems + group + } + else -> null + } + } + } + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/GroupItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/GroupItem.kt index 2ca1c67c22..9854c8ae7b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/GroupItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/GroupItem.kt @@ -44,7 +44,7 @@ class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem) : ExpandableViewHolder(view, adapter, true) { + open class Holder(view: View, adapter: FlexibleAdapter<*>) : ExpandableViewHolder(view, adapter, true) { val title = itemView.findViewById(R.id.title) as TextView val icon = itemView.findViewById(R.id.expand_icon) as ImageView diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SectionItems.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SectionItems.kt index 0470f6beb1..338c231123 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SectionItems.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SectionItems.kt @@ -12,6 +12,18 @@ class TriStateSectionItem(filter: Filter.TriState) : TriStateItem(filter), ISect override fun setHeader(header: GroupItem?) { head = header } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is TriStateSectionItem) { + return filter == other.filter + } + return false + } + + override fun hashCode(): Int { + return filter.hashCode() + } } class TextSectionItem(filter: Filter.Text) : TextItem(filter), ISectionable { @@ -23,6 +35,18 @@ class TextSectionItem(filter: Filter.Text) : TextItem(filter), ISectionable { @@ -34,6 +58,18 @@ class CheckboxSectionItem(filter: Filter.CheckBox) : CheckboxItem(filter), ISect override fun setHeader(header: GroupItem?) { head = header } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is CheckboxSectionItem) { + return filter == other.filter + } + return false + } + + override fun hashCode(): Int { + return filter.hashCode() + } } class SelectSectionItem(filter: Filter.Select<*>) : SelectItem(filter), ISectionable { @@ -45,4 +81,16 @@ class SelectSectionItem(filter: Filter.Select<*>) : SelectItem(filter), ISection override fun setHeader(header: GroupItem?) { head = header } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is SelectSectionItem) { + return filter == other.filter + } + return false + } + + override fun hashCode(): Int { + return filter.hashCode() + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortGroup.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortGroup.kt index b97c71abf6..b397538108 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortGroup.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortGroup.kt @@ -3,24 +3,22 @@ package eu.kanade.tachiyomi.ui.catalogue.filter import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem import eu.davidea.flexibleadapter.items.ISectionable -import eu.davidea.viewholders.ExpandableViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.source.model.Filter import eu.kanade.tachiyomi.util.setVectorCompat class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem>() { + // Use an id instead of the layout res to allow to reuse the layout. override fun getLayoutRes(): Int { - return R.layout.navigation_view_sort + return R.id.catalogue_filter_sort_group } override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder { - return Holder(inflater.inflate(layoutRes, parent, false), adapter) + return Holder(inflater.inflate(R.layout.navigation_view_group, parent, false), adapter) } override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List?) { @@ -44,14 +42,5 @@ class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem) : ExpandableViewHolder(view, adapter, true) { - - val title = itemView.findViewById(R.id.title) as TextView - val icon = itemView.findViewById(R.id.expand_icon) as ImageView - - override fun shouldNotifyParentOnClick(): Boolean { - return true - } - } - + class Holder(view: View, adapter: FlexibleAdapter<*>) : GroupItem.Holder(view, adapter) } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortItem.kt index 008e4524af..6bc1a1252b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/filter/SortItem.kt @@ -15,12 +15,13 @@ import eu.kanade.tachiyomi.util.getResourceColor class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem(group) { + // Use an id instead of the layout res to allow to reuse the layout. override fun getLayoutRes(): Int { - return R.layout.navigation_view_sort_item + return R.id.catalogue_filter_sort_item } override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder { - return Holder(inflater.inflate(layoutRes, parent, false), adapter) + return Holder(inflater.inflate(R.layout.navigation_view_checkedtext, parent, false), adapter) } override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List?) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt index 28c4f7bbc0..a8cceabe53 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt @@ -92,7 +92,7 @@ class CategoryActivity : */ fun setCategories(categories: List) { actionMode?.finish() - adapter.updateDataSet(categories) + adapter.updateDataSet(categories.toMutableList()) val selected = categories.filter { it.isSelected } if (selected.isNotEmpty()) { selected.forEach { onItemLongClick(categories.indexOf(it)) } diff --git a/app/src/main/res/layout/navigation_view_sort.xml b/app/src/main/res/layout/navigation_view_sort.xml deleted file mode 100644 index d3399c50fc..0000000000 --- a/app/src/main/res/layout/navigation_view_sort.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/navigation_view_sort_item.xml b/app/src/main/res/layout/navigation_view_sort_item.xml deleted file mode 100644 index 7358b6f298..0000000000 --- a/app/src/main/res/layout/navigation_view_sort_item.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/navigation_view_text.xml b/app/src/main/res/layout/navigation_view_text.xml index 9ac9909d1c..5ca0da1755 100644 --- a/app/src/main/res/layout/navigation_view_text.xml +++ b/app/src/main/res/layout/navigation_view_text.xml @@ -15,7 +15,7 @@ android:layout_weight="1" android:gravity="center_vertical|start"> - + + + + + \ No newline at end of file