mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Implement latest updates. (#472)
This commit is contained in:
		| @@ -53,6 +53,11 @@ abstract class OnlineSource(context: Context) : Source { | ||||
|      */ | ||||
|     abstract val lang: Language | ||||
|  | ||||
|     /** | ||||
|      * If the Source has Support for Latest Updates | ||||
|      */ | ||||
|     abstract val supportsLatest : Boolean | ||||
|  | ||||
|     /** | ||||
|      * Headers used for requests. | ||||
|      */ | ||||
| @@ -96,6 +101,17 @@ abstract class OnlineSource(context: Context) : Source { | ||||
|                 page | ||||
|             } | ||||
|  | ||||
|     /** | ||||
|      * Returns an observable containing a page with a list of latest manga. | ||||
|      */ | ||||
|     open fun fetchLatestUpdates(page: MangasPage): Observable<MangasPage> = client | ||||
|             .newCall(latestUpdatesRequest(page)) | ||||
|             .asObservable() | ||||
|             .map { response -> | ||||
|                 latestUpdatesParse(response, page) | ||||
|                 page | ||||
|             } | ||||
|  | ||||
|     /** | ||||
|      * Returns the request for the popular manga given the page. Override only if it's needed to | ||||
|      * send different headers or request method like POST. | ||||
| @@ -109,11 +125,26 @@ abstract class OnlineSource(context: Context) : Source { | ||||
|         return GET(page.url, headers) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the request for latest manga given the page. | ||||
|      */ | ||||
|     open protected fun latestUpdatesRequest(page: MangasPage): Request { | ||||
|         if (page.page == 1) { | ||||
|             page.url = latestUpdatesInitialUrl() | ||||
|         } | ||||
|         return GET(page.url, headers) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the absolute url of the first page to popular manga. | ||||
|      */ | ||||
|     abstract protected fun popularMangaInitialUrl(): String | ||||
|  | ||||
|     /** | ||||
|      * Returns the absolute url of the first page to latest manga. | ||||
|      */ | ||||
|     abstract protected fun latestUpdatesInitialUrl(): String | ||||
|  | ||||
|     /** | ||||
|      * Parse the response from the site. It should add a list of manga and the absolute url to the | ||||
|      * next page (if it has a next one) to [page]. | ||||
| @@ -123,6 +154,11 @@ abstract class OnlineSource(context: Context) : Source { | ||||
|      */ | ||||
|     abstract protected fun popularMangaParse(response: Response, page: MangasPage) | ||||
|  | ||||
|     /** | ||||
|      * Same as [popularMangaParse], but for latest manga. | ||||
|      */ | ||||
|     abstract protected fun latestUpdatesParse(response: Response, page: MangasPage) | ||||
|  | ||||
|     /** | ||||
|      * Returns an observable containing a page with a list of manga. Normally it's not needed to | ||||
|      * override this method. | ||||
|   | ||||
| @@ -37,11 +37,33 @@ abstract class ParsedOnlineSource(context: Context) : OnlineSource(context) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse the response from the site for latest updates and fills [page]. | ||||
|      */ | ||||
|     override fun latestUpdatesParse(response: Response, page: MangasPage) { | ||||
|         val document = response.asJsoup() | ||||
|         for (element in document.select(latestUpdatesSelector())) { | ||||
|             Manga.create(id).apply { | ||||
|                 latestUpdatesFromElement(element, this) | ||||
|                 page.mangas.add(this) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         latestUpdatesNextPageSelector()?.let { selector -> | ||||
|             page.nextPageUrl = document.select(selector).first()?.absUrl("href") | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the Jsoup selector that returns a list of [Element] corresponding to each manga. | ||||
|      */ | ||||
|     abstract protected fun popularMangaSelector(): String | ||||
|  | ||||
|     /** | ||||
|      * Returns the Jsoup selector similar to [popularMangaSelector], but for latest updates. | ||||
|      */ | ||||
|     abstract protected fun latestUpdatesSelector(): String | ||||
|  | ||||
|     /** | ||||
|      * Fills [manga] with the given [element]. Most sites only show the title and the url, it's | ||||
|      * totally safe to fill only those two values. | ||||
| @@ -51,12 +73,22 @@ abstract class ParsedOnlineSource(context: Context) : OnlineSource(context) { | ||||
|      */ | ||||
|     abstract protected fun popularMangaFromElement(element: Element, manga: Manga) | ||||
|  | ||||
|     /** | ||||
|      * Fills [manga] with the given [element]. For latest updates. | ||||
|      */ | ||||
|     abstract protected fun latestUpdatesFromElement(element: Element, manga: Manga) | ||||
|  | ||||
|     /** | ||||
|      * Returns the Jsoup selector that returns the <a> tag linking to the next page, or null if | ||||
|      * there's no next page. | ||||
|      */ | ||||
|     abstract protected fun popularMangaNextPageSelector(): String? | ||||
|  | ||||
|     /** | ||||
|      * Returns the Jsoup selector that returns the <a> tag, like [popularMangaNextPageSelector]. | ||||
|      */ | ||||
|     abstract protected fun latestUpdatesNextPageSelector(): String? | ||||
|  | ||||
|     /** | ||||
|      * Parse the response from the site and fills [page]. | ||||
|      * | ||||
|   | ||||
| @@ -34,6 +34,8 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con | ||||
|         getLanguages().find { code == it.code }!! | ||||
|     } | ||||
|  | ||||
|     override val supportsLatest = map.supportsLatest.toBoolean() | ||||
|  | ||||
|     override val client = when(map.client) { | ||||
|         "cloudflare" -> network.cloudflareClient | ||||
|         else -> network.client | ||||
| @@ -53,8 +55,20 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesRequest(page: MangasPage): Request { | ||||
|         if (page.page == 1) { | ||||
|             page.url = latestUpdatesInitialUrl() | ||||
|         } | ||||
|         return when (map.latestupdates.method?.toLowerCase()) { | ||||
|             "post" -> POST(page.url, headers, map.latestupdates.createForm()) | ||||
|             else -> GET(page.url, headers) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = map.popular.url | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = map.latestupdates.url | ||||
|  | ||||
|     override fun popularMangaParse(response: Response, page: MangasPage) { | ||||
|         val document = response.asJsoup() | ||||
|         for (element in document.select(map.popular.manga_css)) { | ||||
| @@ -70,6 +84,21 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesParse(response: Response, page: MangasPage) { | ||||
|         val document = response.asJsoup() | ||||
|         for (element in document.select(map.latestupdates.manga_css)) { | ||||
|             Manga.create(id).apply { | ||||
|                 title = element.text() | ||||
|                 setUrlWithoutDomain(element.attr("href")) | ||||
|                 page.mangas.add(this) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         map.popular.next_url_css?.let { selector -> | ||||
|             page.nextPageUrl = document.select(selector).first()?.absUrl("href") | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun searchMangaRequest(page: MangasPage, query: String, filters: List<Filter>): Request { | ||||
|         if (page.page == 1) { | ||||
|             page.url = searchMangaInitialUrl(query, filters) | ||||
|   | ||||
| @@ -25,11 +25,15 @@ class YamlSourceNode(uncheckedMap: Map<*, *>) { | ||||
|  | ||||
|     val lang: String by map | ||||
|  | ||||
|     val supportsLatest: String by map | ||||
|  | ||||
|     val client: String? | ||||
|         get() = map["client"] as? String | ||||
|  | ||||
|     val popular = PopularNode(toMap(map["popular"])!!) | ||||
|  | ||||
|     val latestupdates = LatestUpdatesNode(toMap(map["latest_updates"])!!) | ||||
|  | ||||
|     val search = SearchNode(toMap(map["search"])!!) | ||||
|  | ||||
|     val manga = MangaNode(toMap(map["manga"])!!) | ||||
| @@ -73,6 +77,17 @@ class PopularNode(override val map: Map<String, Any?>): RequestableNode { | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| class LatestUpdatesNode(override val map: Map<String, Any?>): RequestableNode { | ||||
|  | ||||
|     val manga_css: String by map | ||||
|  | ||||
|     val next_url_css: String? | ||||
|         get() = map["next_url_css"] as? String | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| class SearchNode(override val map: Map<String, Any?>): RequestableNode { | ||||
|  | ||||
|     val manga_css: String by map | ||||
|   | ||||
| @@ -36,6 +36,8 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     private val datePattern = Pattern.compile("(\\d+|A|An)\\s+(.*?)s? ago.*") | ||||
|  | ||||
|     private val dateFields = HashMap<String, Int>().apply { | ||||
| @@ -59,6 +61,8 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/search_ajax?order_cond=views&order=desc&p=1" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/search_ajax?order_cond=update&order=desc&p=1" | ||||
|  | ||||
|     override fun popularMangaParse(response: Response, page: MangasPage) { | ||||
|         val document = response.asJsoup() | ||||
|         for (element in document.select(popularMangaSelector())) { | ||||
| @@ -73,8 +77,24 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesParse(response: Response, page: MangasPage) { | ||||
|         val document = response.asJsoup() | ||||
|         for (element in document.select(latestUpdatesSelector())) { | ||||
|             Manga.create(id).apply { | ||||
|                 latestUpdatesFromElement(element, this) | ||||
|                 page.mangas.add(this) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         page.nextPageUrl = document.select(latestUpdatesNextPageSelector()).first()?.let { | ||||
|             "$baseUrl/search_ajax?order_cond=update&order=desc&p=${page.page + 1}" | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaSelector() = "tr:has(a)" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "tr:has(a)" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("a[href^=http://bato.to]").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -82,8 +102,14 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "#show_more_row" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "#show_more_row" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = "$baseUrl/search_ajax?name=${Uri.encode(query)}&order_cond=views&order=desc&p=1&genre_cond=and&genres=${getFilterParams(filters)}" | ||||
|  | ||||
|     private fun getFilterParams(filters: List<Filter>): String = filters | ||||
| @@ -320,4 +346,5 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex | ||||
|             Filter("29", "Yaoi"), | ||||
|             Filter("31", "Yuri") | ||||
|     ) | ||||
|  | ||||
| } | ||||
| @@ -27,12 +27,18 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override val client: OkHttpClient get() = network.cloudflareClient | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override val client: OkHttpClient = network.cloudflareClient | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/MangaList/MostPopular" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "http://kissmanga.com/MangaList/LatestUpdate" | ||||
|  | ||||
|     override fun popularMangaSelector() = "table.listing tr:gt(1)" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "table.listing tr:gt(1)" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("td a:eq(0)").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -40,8 +46,14 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "li > a:contains(› Next)" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector(): String = "ul.pager > li > a:contains(Next)" | ||||
|  | ||||
|     override fun searchMangaRequest(page: MangasPage, query: String, filters: List<Filter>): Request { | ||||
|         if (page.page == 1) { | ||||
|             page.url = searchMangaInitialUrl(query, filters) | ||||
|   | ||||
| @@ -23,10 +23,16 @@ class Mangafox(context: Context, override val id: Int) : ParsedOnlineSource(cont | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/directory/" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/directory/?latest" | ||||
|  | ||||
|     override fun popularMangaSelector() = "div#mangalist > ul.list > li" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "div#mangalist > ul.list > li" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("a.title").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -34,8 +40,14 @@ class Mangafox(context: Context, override val id: Int) : ParsedOnlineSource(cont | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "a:has(span.next)" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "a:has(span.next)" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = | ||||
|             "$baseUrl/search.php?name_method=cw&advopts=1&order=za&sort=views&name=$query&page=1&${filters.map { it.id + "=1" }.joinToString("&")}" | ||||
|  | ||||
| @@ -157,4 +169,5 @@ class Mangafox(context: Context, override val id: Int) : ParsedOnlineSource(cont | ||||
|             Filter("genres[Yaoi]", "Yaoi"), | ||||
|             Filter("genres[Yuri]", "Yuri") | ||||
|     ) | ||||
|  | ||||
| } | ||||
| @@ -1,7 +1,6 @@ | ||||
| package eu.kanade.tachiyomi.data.source.online.english | ||||
|  | ||||
| import android.content.Context | ||||
| import android.util.Log | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.tachiyomi.data.source.EN | ||||
| @@ -22,10 +21,16 @@ class Mangahere(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/directory/" | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/directory/?views.za" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/directory/?last_chapter_time.za" | ||||
|  | ||||
|     override fun popularMangaSelector() = "div.directory_list > ul > li" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "div.directory_list > ul > li" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("div.title > a").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -33,8 +38,14 @@ class Mangahere(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "div.next-page > a.next" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "div.next-page > a.next" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = "$baseUrl/search.php?name=$query&page=1&sort=views&order=za&${filters.map { it.id + "=1" }.joinToString("&")}&advopts=1" | ||||
|  | ||||
|     override fun searchMangaSelector() = "div.result_search > dl:has(dt)" | ||||
| @@ -146,4 +157,5 @@ class Mangahere(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|             Filter("genres[Yaoi]", "Yaoi"), | ||||
|             Filter("genres[Yuri]", "Yuri") | ||||
|     ) | ||||
|  | ||||
| } | ||||
| @@ -22,6 +22,8 @@ class Mangasee(context: Context, override val id: Int) : ParsedOnlineSource(cont | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override val supportsLatest = false | ||||
|  | ||||
|     private val datePattern = Pattern.compile("(\\d+)\\s+(.*?)s? (from now|ago).*") | ||||
|  | ||||
|     private val dateFields = HashMap<String, Int>().apply { | ||||
| @@ -168,4 +170,21 @@ class Mangasee(context: Context, override val id: Int) : ParsedOnlineSource(cont | ||||
|             Filter("Yaoi", "Yaoi"), | ||||
|             Filter("Yuri", "Yuri") | ||||
|     ) | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesSelector(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.tachiyomi.data.network.POST | ||||
| import eu.kanade.tachiyomi.data.source.EN | ||||
| import eu.kanade.tachiyomi.data.source.Language | ||||
| import eu.kanade.tachiyomi.data.source.Source | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage | ||||
| import eu.kanade.tachiyomi.data.source.model.Page | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource | ||||
| @@ -26,6 +25,8 @@ class Readmangatoday(context: Context, override val id: Int) : ParsedOnlineSourc | ||||
|  | ||||
|     override val lang: Language get() = EN | ||||
|  | ||||
|     override val supportsLatest = false | ||||
|  | ||||
|     override val client: OkHttpClient get() = network.cloudflareClient | ||||
|  | ||||
|     /** | ||||
| @@ -182,4 +183,21 @@ class Readmangatoday(context: Context, override val id: Int) : ParsedOnlineSourc | ||||
|             Filter("36", "Yaoi"), | ||||
|             Filter("37", "Yuri") | ||||
|     ) | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesSelector(): String { | ||||
|         throw UnsupportedOperationException("not implemented") | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -15,83 +15,95 @@ import java.text.SimpleDateFormat | ||||
|  | ||||
| class WieManga(context: Context, override val id: Int) : ParsedOnlineSource(context) { | ||||
|  | ||||
|         override val name = "Wie Manga!" | ||||
|     override val name = "Wie Manga!" | ||||
|  | ||||
|         override val baseUrl = "http://www.wiemanga.com" | ||||
|     override val baseUrl = "http://www.wiemanga.com" | ||||
|  | ||||
|         override val lang: Language get() = DE | ||||
|     override val lang: Language get() = DE | ||||
|  | ||||
|         override fun popularMangaInitialUrl() = "$baseUrl/list/Hot-Book/" | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|         override fun popularMangaSelector() = ".booklist td > div" | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/list/Hot-Book/" | ||||
|  | ||||
|         override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|                 val image = element.select("dt img") | ||||
|                 val title = element.select("dd a:first-child") | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/list/New-Update/" | ||||
|  | ||||
|                 manga.setUrlWithoutDomain(title.attr("href")) | ||||
|                 manga.title = title.text() | ||||
|                 manga.thumbnail_url = image.attr("src") | ||||
|     override fun popularMangaSelector() = ".booklist td > div" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = ".booklist td > div" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         val image = element.select("dt img") | ||||
|         val title = element.select("dd a:first-child") | ||||
|  | ||||
|         manga.setUrlWithoutDomain(title.attr("href")) | ||||
|         manga.title = title.text() | ||||
|         manga.thumbnail_url = image.attr("src") | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = null | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = null | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = "$baseUrl/search/?wd=$query" | ||||
|  | ||||
|     override fun searchMangaSelector() = ".searchresult td > div" | ||||
|  | ||||
|     override fun searchMangaFromElement(element: Element, manga: Manga) { | ||||
|         val image = element.select(".resultimg img") | ||||
|         val title = element.select(".resultbookname") | ||||
|  | ||||
|         manga.setUrlWithoutDomain(title.attr("href")) | ||||
|         manga.title = title.text() | ||||
|         manga.thumbnail_url = image.attr("src") | ||||
|     } | ||||
|  | ||||
|     override fun searchMangaNextPageSelector() = ".pagetor a.l" | ||||
|  | ||||
|     override fun mangaDetailsParse(document: Document, manga: Manga) { | ||||
|         val imageElement = document.select(".bookmessgae tr > td:nth-child(1)").first() | ||||
|         val infoElement = document.select(".bookmessgae tr > td:nth-child(2)").first() | ||||
|  | ||||
|         manga.author = infoElement.select("dd:nth-of-type(2) a").first()?.text() | ||||
|         manga.artist = infoElement.select("dd:nth-of-type(3) a").first()?.text() | ||||
|         manga.description = infoElement.select("dl > dt:last-child").first()?.text()?.replaceFirst("Beschreibung", "") | ||||
|         manga.thumbnail_url = imageElement.select("img").first()?.attr("src") | ||||
|  | ||||
|         if (manga.author == "RSS") | ||||
|                 manga.author = null | ||||
|  | ||||
|         if (manga.artist == "RSS") | ||||
|                 manga.artist = null | ||||
|     } | ||||
|  | ||||
|     override fun chapterListSelector() = ".chapterlist tr:not(:first-child)" | ||||
|  | ||||
|     override fun chapterFromElement(element: Element, chapter: Chapter) { | ||||
|         val urlElement = element.select(".col1 a").first() | ||||
|         val dateElement = element.select(".col3 a").first() | ||||
|  | ||||
|         chapter.setUrlWithoutDomain(urlElement.attr("href")) | ||||
|         chapter.name = urlElement.text() | ||||
|         chapter.date_upload = dateElement?.text()?.let { parseChapterDate(it) } ?: 0 | ||||
|     } | ||||
|  | ||||
|     private fun parseChapterDate(date: String): Long { | ||||
|         return SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(date).time | ||||
|     } | ||||
|  | ||||
|     override fun pageListParse(response: Response, pages: MutableList<Page>) { | ||||
|         val document = response.asJsoup() | ||||
|  | ||||
|         document.select("select#page").first().select("option").forEach { | ||||
|                 pages.add(Page(pages.size, it.attr("value"))) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         override fun popularMangaNextPageSelector() = null | ||||
|     override fun pageListParse(document: Document, pages: MutableList<Page>) {} | ||||
|  | ||||
|         override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = "$baseUrl/search/?wd=$query" | ||||
|  | ||||
|         override fun searchMangaSelector() = ".searchresult td > div" | ||||
|  | ||||
|         override fun searchMangaFromElement(element: Element, manga: Manga) { | ||||
|                 val image = element.select(".resultimg img") | ||||
|                 val title = element.select(".resultbookname") | ||||
|  | ||||
|                 manga.setUrlWithoutDomain(title.attr("href")) | ||||
|                 manga.title = title.text() | ||||
|                 manga.thumbnail_url = image.attr("src") | ||||
|         } | ||||
|  | ||||
|         override fun searchMangaNextPageSelector() = ".pagetor a.l" | ||||
|  | ||||
|         override fun mangaDetailsParse(document: Document, manga: Manga) { | ||||
|                 val imageElement = document.select(".bookmessgae tr > td:nth-child(1)").first() | ||||
|                 val infoElement = document.select(".bookmessgae tr > td:nth-child(2)").first() | ||||
|  | ||||
|                 manga.author = infoElement.select("dd:nth-of-type(2) a").first()?.text() | ||||
|                 manga.artist = infoElement.select("dd:nth-of-type(3) a").first()?.text() | ||||
|                 manga.description = infoElement.select("dl > dt:last-child").first()?.text()?.replaceFirst("Beschreibung", "") | ||||
|                 manga.thumbnail_url = imageElement.select("img").first()?.attr("src") | ||||
|  | ||||
|                 if (manga.author == "RSS") | ||||
|                         manga.author = null | ||||
|  | ||||
|                 if (manga.artist == "RSS") | ||||
|                         manga.artist = null | ||||
|         } | ||||
|  | ||||
|         override fun chapterListSelector() = ".chapterlist tr:not(:first-child)" | ||||
|  | ||||
|         override fun chapterFromElement(element: Element, chapter: Chapter) { | ||||
|                 val urlElement = element.select(".col1 a").first() | ||||
|                 val dateElement = element.select(".col3 a").first() | ||||
|  | ||||
|                 chapter.setUrlWithoutDomain(urlElement.attr("href")) | ||||
|                 chapter.name = urlElement.text() | ||||
|                 chapter.date_upload = dateElement?.text()?.let { parseChapterDate(it) } ?: 0 | ||||
|         } | ||||
|  | ||||
|         private fun parseChapterDate(date: String): Long { | ||||
|                 return SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(date).time | ||||
|         } | ||||
|  | ||||
|         override fun pageListParse(response: Response, pages: MutableList<Page>) { | ||||
|                 val document = response.asJsoup() | ||||
|  | ||||
|                 document.select("select#page").first().select("option").forEach { | ||||
|                         pages.add(Page(pages.size, it.attr("value"))) | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|         override fun pageListParse(document: Document, pages: MutableList<Page>) {} | ||||
|  | ||||
|         override fun imageUrlParse(document: Document) = document.select("img#comicpic").first().attr("src") | ||||
|     override fun imageUrlParse(document: Document) = document.select("img#comicpic").first().attr("src") | ||||
|  | ||||
| } | ||||
| @@ -21,12 +21,18 @@ class Mangachan(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|  | ||||
|     override val lang: Language get() = RU | ||||
|  | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/mostfavorites" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/manga/new" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = "$baseUrl/?do=search&subaction=search&story=$query" | ||||
|  | ||||
|     override fun popularMangaSelector() = "div.content_row" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "div.content_row" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("h2 > a").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -34,8 +40,14 @@ class Mangachan(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "a:contains(Вперед)" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "a:contains(Вперед)" | ||||
|  | ||||
|     override fun searchMangaSelector() = popularMangaSelector() | ||||
|  | ||||
|     override fun searchMangaFromElement(element: Element, manga: Manga) { | ||||
| @@ -91,4 +103,5 @@ class Mangachan(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|     override fun pageListParse(document: Document, pages: MutableList<Page>) { } | ||||
|  | ||||
|     override fun imageUrlParse(document: Document) = "" | ||||
|  | ||||
| } | ||||
| @@ -22,13 +22,19 @@ class Mintmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|  | ||||
|     override val lang: Language get() = RU | ||||
|  | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/list?sortType=rate" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/list?sortType=updated" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = | ||||
|             "$baseUrl/search?q=$query&${filters.map { it.id + "=in" }.joinToString("&")}" | ||||
|  | ||||
|     override fun popularMangaSelector() = "div.desc" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "div.desc" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("h3 > a").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -36,8 +42,14 @@ class Mintmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "a.nextLink" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "a.nextLink" | ||||
|  | ||||
|     override fun searchMangaSelector() = popularMangaSelector() | ||||
|  | ||||
|     override fun searchMangaFromElement(element: Element, manga: Manga) { | ||||
| @@ -151,4 +163,5 @@ class Mintmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|             Filter("el_1315", "юри"), | ||||
|             Filter("el_1336", "яой") | ||||
|     ) | ||||
|  | ||||
| } | ||||
| @@ -22,13 +22,19 @@ class Readmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|  | ||||
|     override val lang: Language get() = RU | ||||
|  | ||||
|     override val supportsLatest = true | ||||
|  | ||||
|     override fun popularMangaInitialUrl() = "$baseUrl/list?sortType=rate" | ||||
|  | ||||
|     override fun latestUpdatesInitialUrl() = "$baseUrl/list?sortType=updated" | ||||
|  | ||||
|     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) = | ||||
|             "$baseUrl/search?q=$query&${filters.map { it.id + "=in" }.joinToString("&")}" | ||||
|  | ||||
|     override fun popularMangaSelector() = "div.desc" | ||||
|  | ||||
|     override fun latestUpdatesSelector() = "div.desc" | ||||
|  | ||||
|     override fun popularMangaFromElement(element: Element, manga: Manga) { | ||||
|         element.select("h3 > a").first().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
| @@ -36,8 +42,14 @@ class Readmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun latestUpdatesFromElement(element: Element, manga: Manga) { | ||||
|         popularMangaFromElement(element, manga) | ||||
|     } | ||||
|  | ||||
|     override fun popularMangaNextPageSelector() = "a.nextLink" | ||||
|  | ||||
|     override fun latestUpdatesNextPageSelector() = "a.nextLink" | ||||
|  | ||||
|     override fun searchMangaSelector() = popularMangaSelector() | ||||
|  | ||||
|     override fun searchMangaFromElement(element: Element, manga: Manga) { | ||||
| @@ -152,4 +164,5 @@ class Readmanga(context: Context, override val id: Int) : ParsedOnlineSource(con | ||||
|             Filter("el_2149", "этти"), | ||||
|             Filter("el_2123", "юри") | ||||
|     ) | ||||
|  | ||||
| } | ||||
| @@ -41,7 +41,7 @@ import java.util.concurrent.TimeUnit.MILLISECONDS | ||||
|  * Uses R.layout.fragment_catalogue. | ||||
|  */ | ||||
| @RequiresPresenter(CataloguePresenter::class) | ||||
| class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHolder.OnListItemClickListener { | ||||
| open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHolder.OnListItemClickListener { | ||||
|  | ||||
|     /** | ||||
|      * Spinner shown in the toolbar to change the selected source. | ||||
|   | ||||
| @@ -4,19 +4,10 @@ import eu.kanade.tachiyomi.data.source.model.MangasPage | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource.Filter | ||||
| import rx.Observable | ||||
| import rx.subjects.PublishSubject | ||||
|  | ||||
| class CataloguePager(val source: OnlineSource, val query: String, val filters: List<Filter>) { | ||||
| open class CataloguePager(val source: OnlineSource, val query: String, val filters: List<Filter>): Pager() { | ||||
|  | ||||
|     private var lastPage: MangasPage? = null | ||||
|  | ||||
|     private val results = PublishSubject.create<MangasPage>() | ||||
|  | ||||
|     fun results(): Observable<MangasPage> { | ||||
|         return results.asObservable() | ||||
|     } | ||||
|  | ||||
|     fun requestNext(transformer: (Observable<MangasPage>) -> Observable<MangasPage>): Observable<MangasPage> { | ||||
|     override fun requestNext(transformer: (Observable<MangasPage>) -> Observable<MangasPage>): Observable<MangasPage> { | ||||
|         val lastPage = lastPage | ||||
|  | ||||
|         val page = if (lastPage == null) | ||||
| @@ -34,8 +25,4 @@ class CataloguePager(val source: OnlineSource, val query: String, val filters: L | ||||
|                 .doOnNext { this@CataloguePager.lastPage = it } | ||||
|     } | ||||
|  | ||||
|     fun hasNextPage(): Boolean { | ||||
|         return lastPage == null || lastPage?.nextPageUrl != null | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -26,7 +26,7 @@ import java.util.NoSuchElementException | ||||
| /** | ||||
|  * Presenter of [CatalogueFragment]. | ||||
|  */ | ||||
| class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
| open class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|  | ||||
|     /** | ||||
|      * Source manager. | ||||
| @@ -73,7 +73,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|     /** | ||||
|      * Pager containing a list of manga results. | ||||
|      */ | ||||
|     private lateinit var pager: CataloguePager | ||||
|     private lateinit var pager: Pager | ||||
|  | ||||
|     /** | ||||
|      * Subject that initializes a list of manga. | ||||
| @@ -140,7 +140,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|         } | ||||
|  | ||||
|         // Create a new pager. | ||||
|         pager = CataloguePager(source, query, filters) | ||||
|         pager = createPager(query, filters) | ||||
|  | ||||
|         // Prepare the pager. | ||||
|         pagerSubscription?.let { remove(it) } | ||||
| @@ -305,7 +305,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|      * @param source the source to check. | ||||
|      * @return true if the source is valid, false otherwise. | ||||
|      */ | ||||
|     fun isValidSource(source: Source?): Boolean { | ||||
|     open fun isValidSource(source: Source?): Boolean { | ||||
|         if (source == null) return false | ||||
|  | ||||
|         if (source is LoginSource) { | ||||
| @@ -327,7 +327,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|     /** | ||||
|      * Returns a list of enabled sources ordered by language and name. | ||||
|      */ | ||||
|     private fun getEnabledSources(): List<OnlineSource> { | ||||
|     open protected fun getEnabledSources(): List<OnlineSource> { | ||||
|         val languages = prefs.enabledLanguages().getOrDefault() | ||||
|         val hiddenCatalogues = prefs.hiddenCatalogues().getOrDefault() | ||||
|  | ||||
| @@ -371,4 +371,8 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() { | ||||
|         restartPager(filters = selectedFilters) | ||||
|     } | ||||
|  | ||||
|     open fun createPager(query: String, filters: List<Filter>): Pager { | ||||
|         return CataloguePager(source, query, filters) | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										25
									
								
								app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/Pager.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/Pager.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package eu.kanade.tachiyomi.ui.catalogue | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage | ||||
| import rx.subjects.PublishSubject | ||||
| import rx.Observable | ||||
|  | ||||
| /** | ||||
|  * A general pager for source requests (latest updates, popular, search) | ||||
|  */ | ||||
| abstract class Pager { | ||||
|  | ||||
|     protected var lastPage: MangasPage? = null | ||||
|  | ||||
|     protected val results = PublishSubject.create<MangasPage>() | ||||
|  | ||||
|     fun results(): Observable<MangasPage> { | ||||
|         return results.asObservable() | ||||
|     } | ||||
|  | ||||
|     fun hasNextPage(): Boolean { | ||||
|         return lastPage == null || lastPage?.nextPageUrl != null | ||||
|     } | ||||
|  | ||||
|     abstract fun requestNext(transformer: (Observable<MangasPage>) -> Observable<MangasPage>): Observable<MangasPage> | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| package eu.kanade.tachiyomi.ui.latest_updates | ||||
|  | ||||
| import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment | ||||
| import nucleus.factory.RequiresPresenter | ||||
| import android.view.* | ||||
| import eu.kanade.tachiyomi.R | ||||
|  | ||||
| /** | ||||
|  * Fragment that shows the manga from the catalogue. Inherit CatalogueFragment. | ||||
|  */ | ||||
| @RequiresPresenter(LatestUpdatesPresenter::class) | ||||
| class LatestUpdatesFragment : CatalogueFragment() { | ||||
|  | ||||
|     override fun onPrepareOptionsMenu(menu: Menu) { | ||||
|         super.onPrepareOptionsMenu(menu) | ||||
|         menu.findItem(R.id.action_search).isVisible = false | ||||
|         menu.findItem(R.id.action_set_filter).isVisible = false | ||||
|  | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|  | ||||
|         fun newInstance(): LatestUpdatesFragment { | ||||
|             return LatestUpdatesFragment() | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| package eu.kanade.tachiyomi.ui.latest_updates | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.source.model.MangasPage | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource | ||||
| import eu.kanade.tachiyomi.ui.catalogue.Pager | ||||
| import rx.Observable | ||||
|  | ||||
| /** | ||||
|  * LatestUpdatesPager inherited from the general Pager. | ||||
|  */ | ||||
| class LatestUpdatesPager(val source: OnlineSource): Pager() { | ||||
|  | ||||
|     override fun requestNext(transformer: (Observable<MangasPage>) -> Observable<MangasPage>): Observable<MangasPage> { | ||||
|         val lastPage = lastPage | ||||
|  | ||||
|         val page = if (lastPage == null) | ||||
|             MangasPage(1) | ||||
|         else | ||||
|             MangasPage(lastPage.page + 1).apply { url = lastPage.nextPageUrl!! } | ||||
|  | ||||
|         val observable = source.fetchLatestUpdates(page) | ||||
|  | ||||
|         return transformer(observable) | ||||
|                 .doOnNext { results.onNext(it) } | ||||
|                 .doOnNext { this@LatestUpdatesPager.lastPage = it } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| package eu.kanade.tachiyomi.ui.latest_updates | ||||
|  | ||||
| import eu.kanade.tachiyomi.data.source.Source | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource | ||||
| import eu.kanade.tachiyomi.ui.catalogue.CataloguePresenter | ||||
| import eu.kanade.tachiyomi.ui.catalogue.Pager | ||||
| import eu.kanade.tachiyomi.data.source.online.OnlineSource.Filter | ||||
|  | ||||
| /** | ||||
|  * Presenter of [LatestUpdatesFragment]. Inherit CataloguePresenter. | ||||
|  */ | ||||
| class LatestUpdatesPresenter : CataloguePresenter() { | ||||
|  | ||||
|     override fun createPager(query: String, filters: List<Filter>): Pager { | ||||
|         return LatestUpdatesPager(source) | ||||
|     } | ||||
|  | ||||
|     override fun getEnabledSources(): List<OnlineSource> { | ||||
|         return super.getEnabledSources().filter { it.supportsLatest } | ||||
|     } | ||||
|  | ||||
|     override fun isValidSource(source: Source?): Boolean { | ||||
|         return super.isValidSource(source) && (source as OnlineSource).supportsLatest | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.ui.backup.BackupFragment | ||||
| import eu.kanade.tachiyomi.ui.base.activity.BaseActivity | ||||
| import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment | ||||
| import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesFragment | ||||
| import eu.kanade.tachiyomi.ui.download.DownloadFragment | ||||
| import eu.kanade.tachiyomi.ui.library.LibraryFragment | ||||
| import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment | ||||
| @@ -58,9 +59,10 @@ class MainActivity : BaseActivity() { | ||||
|             val id = item.itemId | ||||
|             when (id) { | ||||
|                 R.id.nav_drawer_library -> setFragment(LibraryFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_recently_read -> setFragment(RecentlyReadFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_recent_updates -> setFragment(RecentChaptersFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_recently_read -> setFragment(RecentlyReadFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_latest_updates -> setFragment(LatestUpdatesFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_downloads -> setFragment(DownloadFragment.newInstance(), id) | ||||
|                 R.id.nav_drawer_settings -> { | ||||
|                     val intent = Intent(this, SettingsActivity::class.java) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user