mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-11 21:10:49 +01:00
Complete group filters
This commit is contained in:
parent
e76fb7a524
commit
71ab6d38e4
18 changed files with 217 additions and 193 deletions
|
@ -93,9 +93,19 @@ class Batoto : ParsedOnlineSource(), LoginSource {
|
||||||
is Status -> if (!filter.isIgnored()) {
|
is Status -> if (!filter.isIgnored()) {
|
||||||
url.addQueryParameter("completed", if (filter.isExcluded()) "i" else "c")
|
url.addQueryParameter("completed", if (filter.isExcluded()) "i" else "c")
|
||||||
}
|
}
|
||||||
|
is GenreList -> {
|
||||||
|
filter.state.forEach { filter ->
|
||||||
|
when (filter) {
|
||||||
is Genre -> if (!filter.isIgnored()) {
|
is Genre -> if (!filter.isIgnored()) {
|
||||||
genres += (if (filter.isExcluded()) ";e" else ";i") + filter.id
|
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 -> {
|
is TextField -> {
|
||||||
if (!filter.state.isEmpty()) url.addQueryParameter(filter.key, filter.state)
|
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 TextField(name: String, val key: String) : Filter.Text(name)
|
||||||
private class SelectField(name: String, val key: String, values: Array<ListValue>, state: Int = 0) : Filter.Select<ListValue>(name, values, state)
|
private class SelectField(name: String, val key: String, values: Array<ListValue>, state: Int = 0) : Filter.Select<ListValue>(name, values, state)
|
||||||
private class Flag(name: String, val key: String, val valTrue: String, val valFalse: String) : Filter.CheckBox(name)
|
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<*>>) : Filter.Group<Filter<*>>("Genres", genres)
|
||||||
|
private class OrderBy : Filter.Sort("Order by",
|
||||||
arrayOf("Title", "Author", "Artist", "Rating", "Views", "Last Update"),
|
arrayOf("Title", "Author", "Artist", "Rating", "Views", "Last Update"),
|
||||||
Filter.Sort.Selection(4, false))
|
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(
|
override fun getFilterList() = FilterList(
|
||||||
TextField("Author", "artist_name"),
|
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"))),
|
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(),
|
Status(),
|
||||||
Flag("Exclude mature", "mature", "m", ""),
|
Flag("Exclude mature", "mature", "m", ""),
|
||||||
Filter.Separator(),
|
|
||||||
OrderBy(),
|
OrderBy(),
|
||||||
Filter.Separator(),
|
GenreList(getGenreList())
|
||||||
Filter.Header("Genres"),
|
)
|
||||||
|
|
||||||
|
// [...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"))),
|
SelectField("Inclusion mode", "genre_cond", arrayOf(ListValue("And (all selected genres)", "and"), ListValue("Or (any selected genres) ", "or"))),
|
||||||
Genre("4-Koma", 40),
|
Genre("4-Koma", 40),
|
||||||
Genre("Action", 1),
|
Genre("Action", 1),
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Kissmanga : ParsedOnlineSource() {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is Author -> add("authorArtist", filter.state)
|
is Author -> add("authorArtist", filter.state)
|
||||||
is Status -> add("status", arrayOf("", "Completed", "Ongoing")[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) = ""
|
override fun imageUrlParse(document: Document) = ""
|
||||||
|
|
||||||
private class Status() : Filter.TriState("Completed")
|
private class Status : Filter.TriState("Completed")
|
||||||
private class Author() : Filter.Text("Author")
|
private class Author : Filter.Text("Author")
|
||||||
private class Genre(name: String) : Filter.TriState(name)
|
private class Genre(name: String) : Filter.TriState(name)
|
||||||
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("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(
|
override fun getFilterList() = FilterList(
|
||||||
Author(),
|
Author(),
|
||||||
Status(),
|
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("4-Koma"),
|
||||||
Genre("Action"),
|
Genre("Action"),
|
||||||
Genre("Adult"),
|
Genre("Adult"),
|
||||||
|
|
|
@ -59,11 +59,7 @@ class Mangafox : ParsedOnlineSource() {
|
||||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is Status -> url.addQueryParameter(filter.id, filter.state.toString())
|
is Status -> url.addQueryParameter(filter.id, filter.state.toString())
|
||||||
is GenreList -> {
|
is GenreList -> filter.state.forEach { genre -> url.addQueryParameter(genre.id, genre.state.toString()) }
|
||||||
filter.state.forEach { genre ->
|
|
||||||
url.addQueryParameter(genre.id, genre.state.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is TextField -> url.addQueryParameter(filter.key, filter.state)
|
is TextField -> url.addQueryParameter(filter.key, filter.state)
|
||||||
is Type -> url.addQueryParameter("type", if(filter.state == 0) "" else filter.state.toString())
|
is Type -> url.addQueryParameter("type", if(filter.state == 0) "" else filter.state.toString())
|
||||||
is OrderBy -> {
|
is OrderBy -> {
|
||||||
|
@ -180,9 +176,7 @@ class Mangafox : ParsedOnlineSource() {
|
||||||
TextField("Artist", "artist"),
|
TextField("Artist", "artist"),
|
||||||
Type(),
|
Type(),
|
||||||
Status(),
|
Status(),
|
||||||
Filter.Separator(),
|
|
||||||
OrderBy(),
|
OrderBy(),
|
||||||
Filter.Separator(),
|
|
||||||
GenreList(getGenreList())
|
GenreList(getGenreList())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Mangahere : ParsedOnlineSource() {
|
||||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is Status -> url.addQueryParameter("is_completed", arrayOf("", "1", "0")[filter.state])
|
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 TextField -> url.addQueryParameter(filter.key, filter.state)
|
||||||
is Type -> url.addQueryParameter("direction", arrayOf("", "rl", "lr")[filter.state])
|
is Type -> url.addQueryParameter("direction", arrayOf("", "rl", "lr")[filter.state])
|
||||||
is OrderBy -> {
|
is OrderBy -> {
|
||||||
|
@ -169,18 +169,20 @@ class Mangahere : ParsedOnlineSource() {
|
||||||
private class OrderBy : Filter.Sort("Order by",
|
private class OrderBy : Filter.Sort("Order by",
|
||||||
arrayOf("Series name", "Rating", "Views", "Total chapters", "Last chapter"),
|
arrayOf("Series name", "Rating", "Views", "Total chapters", "Last chapter"),
|
||||||
Filter.Sort.Selection(2, false))
|
Filter.Sort.Selection(2, false))
|
||||||
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("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(
|
override fun getFilterList() = FilterList(
|
||||||
TextField("Author", "author"),
|
TextField("Author", "author"),
|
||||||
TextField("Artist", "artist"),
|
TextField("Artist", "artist"),
|
||||||
Type(),
|
Type(),
|
||||||
Status(),
|
Status(),
|
||||||
Filter.Separator(),
|
|
||||||
OrderBy(),
|
OrderBy(),
|
||||||
Filter.Separator(),
|
GenreList(getGenreList())
|
||||||
Filter.Header("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
|
||||||
|
private fun getGenreList() = listOf(
|
||||||
Genre("Action"),
|
Genre("Action"),
|
||||||
Genre("Adventure"),
|
Genre("Adventure"),
|
||||||
Genre("Comedy"),
|
Genre("Comedy"),
|
||||||
|
|
|
@ -50,8 +50,8 @@ class Mangasee : ParsedOnlineSource() {
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
val url = HttpUrl.parse("$baseUrl/search/request.php").newBuilder()
|
val url = HttpUrl.parse("$baseUrl/search/request.php").newBuilder()
|
||||||
if (!query.isEmpty()) url.addQueryParameter("keyword", query)
|
if (!query.isEmpty()) url.addQueryParameter("keyword", query)
|
||||||
var genres: String? = null
|
val genres = mutableListOf<String>()
|
||||||
var genresNo: String? = null
|
val genresNo = mutableListOf<String>()
|
||||||
for (filter in if (filters.isEmpty()) getFilterList() else filters) {
|
for (filter in if (filters.isEmpty()) getFilterList() else filters) {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is Sort -> {
|
is Sort -> {
|
||||||
|
@ -62,14 +62,16 @@ class Mangasee : ParsedOnlineSource() {
|
||||||
}
|
}
|
||||||
is SelectField -> if (filter.state != 0) url.addQueryParameter(filter.key, filter.values[filter.state])
|
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 TextField -> if (!filter.state.isEmpty()) url.addQueryParameter(filter.key, filter.state)
|
||||||
is Genre -> when (filter.state) {
|
is GenreList -> filter.state.forEach { genre ->
|
||||||
Filter.TriState.STATE_INCLUDE -> genres = if (genres == null) filter.name else genres + "," + filter.name
|
when (genre.state) {
|
||||||
Filter.TriState.STATE_EXCLUDE -> genresNo = if (genresNo == null) filter.name else genresNo + "," + filter.name
|
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())
|
val (body, requestUrl) = convertQueryToPost(page, url.toString())
|
||||||
return POST(requestUrl, headers, body.build())
|
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 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 Sort : Filter.Sort("Sort", arrayOf("Alphabetically", "Date updated", "Popularity"), Filter.Sort.Selection(2, false))
|
||||||
private class Genre(name: String) : Filter.TriState(name)
|
private class Genre(name: String) : Filter.TriState(name)
|
||||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||||
private class SelectField(name: String, val key: String, values: Array<String>, state: Int = 0) : Filter.Select<String>(name, values, state)
|
private class SelectField(name: String, val key: String, values: Array<String>, state: Int = 0) : Filter.Select<String>(name, values, state)
|
||||||
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("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(
|
override fun getFilterList() = FilterList(
|
||||||
TextField("Years", "year"),
|
TextField("Years", "year"),
|
||||||
TextField("Author", "author"),
|
TextField("Author", "author"),
|
||||||
SelectField("Scan Status", "status", arrayOf("Any", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing")),
|
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("Publish Status", "pstatus", arrayOf("Any", "Cancelled", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing", "Unfinished")),
|
||||||
SelectField("Type", "type", arrayOf("Any", "Doujinshi", "Manga", "Manhua", "Manhwa", "OEL", "One-shot")),
|
SelectField("Type", "type", arrayOf("Any", "Doujinshi", "Manga", "Manhua", "Manhwa", "OEL", "One-shot")),
|
||||||
Filter.Separator(),
|
|
||||||
Sort(),
|
Sort(),
|
||||||
Filter.Separator(),
|
GenreList(getGenreList())
|
||||||
Filter.Header("Genres"),
|
)
|
||||||
|
|
||||||
|
// [...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("Action"),
|
||||||
Genre("Adult"),
|
Genre("Adult"),
|
||||||
Genre("Adventure"),
|
Genre("Adventure"),
|
||||||
|
@ -210,30 +240,4 @@ class Mangasee : ParsedOnlineSource() {
|
||||||
Genre("Yuri")
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -70,9 +70,11 @@ class Readmangatoday : ParsedOnlineSource() {
|
||||||
is TextField -> builder.add(filter.key, filter.state)
|
is TextField -> builder.add(filter.key, filter.state)
|
||||||
is Type -> builder.add("type", arrayOf("all", "japanese", "korean", "chinese")[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 Status -> builder.add("status", arrayOf("both", "completed", "ongoing")[filter.state])
|
||||||
is Genre -> when (filter.state) {
|
is GenreList -> filter.state.forEach { genre ->
|
||||||
Filter.TriState.STATE_INCLUDE -> builder.add("include[]", filter.id.toString())
|
when (genre.state) {
|
||||||
Filter.TriState.STATE_EXCLUDE -> builder.add("exclude[]", filter.id.toString())
|
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")
|
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 Genre(name: String, val id: Int) : Filter.TriState(name)
|
||||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||||
private class Type() : Filter.Select<String>("Type", arrayOf("All", "Japanese Manga", "Korean Manhwa", "Chinese Manhua"))
|
private class Type : Filter.Select<String>("Type", arrayOf("All", "Japanese Manga", "Korean Manhwa", "Chinese Manhua"))
|
||||||
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("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(
|
override fun getFilterList() = FilterList(
|
||||||
TextField("Author", "author-name"),
|
TextField("Author", "author-name"),
|
||||||
TextField("Artist", "artist-name"),
|
TextField("Artist", "artist-name"),
|
||||||
Type(),
|
Type(),
|
||||||
Status(),
|
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("Action", 2),
|
||||||
Genre("Adventure", 4),
|
Genre("Adventure", 4),
|
||||||
Genre("Comedy", 5),
|
Genre("Comedy", 5),
|
||||||
|
|
|
@ -208,7 +208,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
||||||
showProgressBar()
|
showProgressBar()
|
||||||
adapter.clear()
|
adapter.clear()
|
||||||
presenter.setActiveSource(source)
|
presenter.setActiveSource(source)
|
||||||
navView?.setFilters(presenter.sourceFilters)
|
navView?.setFilters(presenter.filterItems)
|
||||||
activity.invalidateOptionsMenu()
|
activity.invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
||||||
this.navView = navView
|
this.navView = navView
|
||||||
activity.drawer.addView(navView)
|
activity.drawer.addView(navView)
|
||||||
activity.drawer.addDrawerListener(drawerListener)
|
activity.drawer.addDrawerListener(drawerListener)
|
||||||
navView.setFilters(presenter.sourceFilters)
|
navView.setFilters(presenter.filterItems)
|
||||||
|
|
||||||
navView.post {
|
navView.post {
|
||||||
if (isAdded && !activity.drawer.isDrawerOpen(navView))
|
if (isAdded && !activity.drawer.isDrawerOpen(navView))
|
||||||
|
@ -247,7 +247,7 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
|
||||||
presenter.appliedFilters = FilterList()
|
presenter.appliedFilters = FilterList()
|
||||||
val newFilters = presenter.source.getFilterList()
|
val newFilters = presenter.source.getFilterList()
|
||||||
presenter.sourceFilters = newFilters
|
presenter.sourceFilters = newFilters
|
||||||
navView.setFilters(newFilters)
|
navView.setFilters(presenter.filterItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
showProgressBar()
|
showProgressBar()
|
||||||
|
|
|
@ -5,11 +5,7 @@ import android.util.AttributeSet
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.davidea.flexibleadapter.items.ISectionable
|
|
||||||
import eu.kanade.tachiyomi.R
|
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.util.inflate
|
||||||
import eu.kanade.tachiyomi.widget.SimpleNavigationView
|
import eu.kanade.tachiyomi.widget.SimpleNavigationView
|
||||||
import kotlinx.android.synthetic.main.catalogue_drawer_content.view.*
|
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)
|
class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||||
: SimpleNavigationView(context, attrs) {
|
: SimpleNavigationView(context, attrs) {
|
||||||
|
|
||||||
val adapter = FlexibleAdapter<IFlexible<*>>(null)
|
val adapter: FlexibleAdapter<IFlexible<*>> = FlexibleAdapter<IFlexible<*>>(null)
|
||||||
|
.setDisplayHeadersAtStartUp(true)
|
||||||
|
.setStickyHeaders(true)
|
||||||
|
|
||||||
var onSearchClicked = {}
|
var onSearchClicked = {}
|
||||||
|
|
||||||
|
@ -26,53 +24,17 @@ class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs:
|
||||||
|
|
||||||
init {
|
init {
|
||||||
recycler.adapter = adapter
|
recycler.adapter = adapter
|
||||||
|
recycler.setHasFixedSize(true)
|
||||||
val view = inflate(R.layout.catalogue_drawer_content)
|
val view = inflate(R.layout.catalogue_drawer_content)
|
||||||
((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler)
|
((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler)
|
||||||
addView(view)
|
addView(view)
|
||||||
|
|
||||||
search_btn.setOnClickListener { onSearchClicked() }
|
search_btn.setOnClickListener { onSearchClicked() }
|
||||||
reset_btn.setOnClickListener { onResetClicked() }
|
reset_btn.setOnClickListener { onResetClicked() }
|
||||||
|
|
||||||
adapter.setDisplayHeadersAtStartUp(true)
|
|
||||||
adapter.setStickyHeaders(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFilters(filters: FilterList) {
|
fun setFilters(items: List<IFlexible<*>>) {
|
||||||
val items = filters.mapNotNull {
|
adapter.updateDataSet(items.toMutableList())
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package eu.kanade.tachiyomi.ui.catalogue
|
package eu.kanade.tachiyomi.ui.catalogue
|
||||||
|
|
||||||
import android.os.Bundle
|
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.cache.CoverCache
|
||||||
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
|
||||||
|
@ -9,10 +11,12 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.source.CatalogueSource
|
import eu.kanade.tachiyomi.data.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.data.source.Source
|
import eu.kanade.tachiyomi.data.source.Source
|
||||||
import eu.kanade.tachiyomi.data.source.SourceManager
|
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.FilterList
|
||||||
import eu.kanade.tachiyomi.data.source.model.SManga
|
import eu.kanade.tachiyomi.data.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.data.source.online.LoginSource
|
import eu.kanade.tachiyomi.data.source.online.LoginSource
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import eu.kanade.tachiyomi.ui.catalogue.filter.*
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
@ -68,6 +72,12 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||||
* Modifiable list of filters.
|
* Modifiable list of filters.
|
||||||
*/
|
*/
|
||||||
var sourceFilters = FilterList()
|
var sourceFilters = FilterList()
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
filterItems = value.toItems()
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterItems: List<IFlexible<*>> = emptyList()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of filters used by the [Pager]. If empty alongside [query], the popular query is used.
|
* List of filters used by the [Pager]. If empty alongside [query], the popular query is used.
|
||||||
|
@ -362,4 +372,41 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||||
return CataloguePager(source, query, filters)
|
return CataloguePager(source, query, filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FilterList.toItems(): List<IFlexible<*>> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<Grou
|
||||||
return filter.hashCode()
|
return filter.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder(view: View, adapter: FlexibleAdapter<*>) : 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 title = itemView.findViewById(R.id.title) as TextView
|
||||||
val icon = itemView.findViewById(R.id.expand_icon) as ImageView
|
val icon = itemView.findViewById(R.id.expand_icon) as ImageView
|
||||||
|
|
|
@ -12,6 +12,18 @@ class TriStateSectionItem(filter: Filter.TriState) : TriStateItem(filter), ISect
|
||||||
override fun setHeader(header: GroupItem?) {
|
override fun setHeader(header: GroupItem?) {
|
||||||
head = header
|
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<TextItem.Holder, GroupItem> {
|
class TextSectionItem(filter: Filter.Text) : TextItem(filter), ISectionable<TextItem.Holder, GroupItem> {
|
||||||
|
@ -23,6 +35,18 @@ class TextSectionItem(filter: Filter.Text) : TextItem(filter), ISectionable<Text
|
||||||
override fun setHeader(header: GroupItem?) {
|
override fun setHeader(header: GroupItem?) {
|
||||||
head = header
|
head = header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other is TextSectionItem) {
|
||||||
|
return filter == other.filter
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return filter.hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckboxSectionItem(filter: Filter.CheckBox) : CheckboxItem(filter), ISectionable<CheckboxItem.Holder, GroupItem> {
|
class CheckboxSectionItem(filter: Filter.CheckBox) : CheckboxItem(filter), ISectionable<CheckboxItem.Holder, GroupItem> {
|
||||||
|
@ -34,6 +58,18 @@ class CheckboxSectionItem(filter: Filter.CheckBox) : CheckboxItem(filter), ISect
|
||||||
override fun setHeader(header: GroupItem?) {
|
override fun setHeader(header: GroupItem?) {
|
||||||
head = header
|
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<SelectItem.Holder, GroupItem> {
|
class SelectSectionItem(filter: Filter.Select<*>) : SelectItem(filter), ISectionable<SelectItem.Holder, GroupItem> {
|
||||||
|
@ -45,4 +81,16 @@ class SelectSectionItem(filter: Filter.Select<*>) : SelectItem(filter), ISection
|
||||||
override fun setHeader(header: GroupItem?) {
|
override fun setHeader(header: GroupItem?) {
|
||||||
head = header
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,22 @@ package eu.kanade.tachiyomi.ui.catalogue.filter
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
|
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.ISectionable
|
import eu.davidea.flexibleadapter.items.ISectionable
|
||||||
import eu.davidea.viewholders.ExpandableViewHolder
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.source.model.Filter
|
import eu.kanade.tachiyomi.data.source.model.Filter
|
||||||
import eu.kanade.tachiyomi.util.setVectorCompat
|
import eu.kanade.tachiyomi.util.setVectorCompat
|
||||||
|
|
||||||
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {
|
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {
|
||||||
|
|
||||||
|
// Use an id instead of the layout res to allow to reuse the layout.
|
||||||
override fun getLayoutRes(): Int {
|
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 {
|
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<Any?>?) {
|
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
|
||||||
|
@ -44,14 +42,5 @@ class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGrou
|
||||||
return filter.hashCode()
|
return filter.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder(view: View, adapter: FlexibleAdapter<*>) : ExpandableViewHolder(view, adapter, true) {
|
class Holder(view: View, adapter: FlexibleAdapter<*>) : GroupItem.Holder(view, adapter)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,12 +15,13 @@ import eu.kanade.tachiyomi.util.getResourceColor
|
||||||
|
|
||||||
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
|
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
|
||||||
|
|
||||||
|
// Use an id instead of the layout res to allow to reuse the layout.
|
||||||
override fun getLayoutRes(): Int {
|
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 {
|
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<Any?>?) {
|
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ class CategoryActivity :
|
||||||
*/
|
*/
|
||||||
fun setCategories(categories: List<CategoryItem>) {
|
fun setCategories(categories: List<CategoryItem>) {
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
adapter.updateDataSet(categories)
|
adapter.updateDataSet(categories.toMutableList())
|
||||||
val selected = categories.filter { it.isSelected }
|
val selected = categories.filter { it.isSelected }
|
||||||
if (selected.isNotEmpty()) {
|
if (selected.isNotEmpty()) {
|
||||||
selected.forEach { onItemLongClick(categories.indexOf(it)) }
|
selected.forEach { onItemLongClick(categories.indexOf(it)) }
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/listPreferredItemHeightSmall"
|
|
||||||
android:background="?colorPrimary"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
|
||||||
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
|
||||||
android:elevation="2dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
|
||||||
android:textColor="@color/textColorPrimaryDark"
|
|
||||||
tools:text="Header"/>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/expand_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/listPreferredItemHeightSmall"
|
|
||||||
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
|
|
||||||
android:paddingRight="?attr/listPreferredItemPaddingRight"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:focusable="true">
|
|
||||||
|
|
||||||
<CheckedTextView
|
|
||||||
android:id="@+id/nav_view_item"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawablePadding="@dimen/material_component_lists_icon_left_padding"
|
|
||||||
android:gravity="center_vertical|start"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -15,7 +15,7 @@
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:gravity="center_vertical|start">
|
android:gravity="center_vertical|start">
|
||||||
|
|
||||||
<EditText
|
<android.support.design.widget.TextInputEditText
|
||||||
android:id="@+id/nav_view_item"
|
android:id="@+id/nav_view_item"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|
6
app/src/main/res/values/ids.xml
Normal file
6
app/src/main/res/values/ids.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<item name="catalogue_filter_sort_group" type="id"/>
|
||||||
|
<item name="catalogue_filter_sort_item" type="id"/>
|
||||||
|
</resources>
|
Loading…
Reference in a new issue