mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-01 22:58:57 +01:00
Rewrite sources. Implement Batoto and Kissmanga
This commit is contained in:
@@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.data.source.EN
|
||||
import eu.kanade.tachiyomi.data.source.SourceManager
|
||||
import eu.kanade.tachiyomi.data.source.base.OnlineSource
|
||||
import eu.kanade.tachiyomi.data.source.base.Source
|
||||
import eu.kanade.tachiyomi.data.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
@@ -52,7 +53,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
/**
|
||||
* Active source.
|
||||
*/
|
||||
lateinit var source: Source
|
||||
lateinit var source: OnlineSource
|
||||
private set
|
||||
|
||||
/**
|
||||
@@ -163,7 +164,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
*
|
||||
* @param source the new active source.
|
||||
*/
|
||||
fun setActiveSource(source: Source) {
|
||||
fun setActiveSource(source: OnlineSource) {
|
||||
prefs.lastUsedCatalogueSource().set(source.id)
|
||||
this.source = source
|
||||
restartPager()
|
||||
@@ -222,9 +223,9 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
}
|
||||
|
||||
val observable = if (query.isEmpty())
|
||||
source.pullPopularMangasFromNetwork(nextMangasPage)
|
||||
source.fetchPopularManga(nextMangasPage)
|
||||
else
|
||||
source.searchMangasFromNetwork(nextMangasPage, query)
|
||||
source.fetchSearchManga(nextMangasPage, query)
|
||||
|
||||
return observable.subscribeOn(Schedulers.io())
|
||||
.doOnNext { lastMangasPage = it }
|
||||
@@ -268,7 +269,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
* @return an observable of the manga to initialize
|
||||
*/
|
||||
private fun getMangaDetailsObservable(manga: Manga): Observable<Manga> {
|
||||
return source.pullMangaFromNetwork(manga.url)
|
||||
return source.fetchMangaDetails(manga)
|
||||
.flatMap { networkManga ->
|
||||
manga.copyFrom(networkManga)
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
@@ -282,13 +283,13 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
*
|
||||
* @return a source.
|
||||
*/
|
||||
fun getLastUsedSource(): Source {
|
||||
fun getLastUsedSource(): OnlineSource {
|
||||
val id = prefs.lastUsedCatalogueSource().get() ?: -1
|
||||
val source = sourceManager.get(id)
|
||||
if (!isValidSource(source)) {
|
||||
return findFirstValidSource()
|
||||
}
|
||||
return source!!
|
||||
return source as OnlineSource
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,10 +299,10 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
* @return true if the source is valid, false otherwise.
|
||||
*/
|
||||
fun isValidSource(source: Source?): Boolean {
|
||||
if (source == null) return false
|
||||
if (source == null || source !is OnlineSource) return false
|
||||
|
||||
return with(source) {
|
||||
if (!isLoginRequired || isLogged) {
|
||||
if (!isLoginRequired() || isLogged()) {
|
||||
true
|
||||
} else {
|
||||
prefs.sourceUsername(this) != "" && prefs.sourcePassword(this) != ""
|
||||
@@ -314,14 +315,14 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
*
|
||||
* @return the index of the first valid source.
|
||||
*/
|
||||
fun findFirstValidSource(): Source {
|
||||
return sources.find { isValidSource(it) }!!
|
||||
fun findFirstValidSource(): OnlineSource {
|
||||
return sources.first { isValidSource(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of enabled sources ordered by language and name.
|
||||
*/
|
||||
private fun getEnabledSources(): List<Source> {
|
||||
private fun getEnabledSources(): List<OnlineSource> {
|
||||
val languages = prefs.enabledLanguages().getOrDefault()
|
||||
|
||||
// Ensure at least one language
|
||||
@@ -329,7 +330,7 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
|
||||
languages.add(EN.code)
|
||||
}
|
||||
|
||||
return sourceManager.getSources()
|
||||
return sourceManager.getOnlineSources()
|
||||
.filter { it.lang.code in languages }
|
||||
.sortedBy { "(${it.lang.code}) ${it.name}" }
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
|
||||
}
|
||||
|
||||
fun getOnlineChaptersObs(): Observable<Pair<Int, Int>> {
|
||||
return source.pullChaptersFromNetwork(manga.url)
|
||||
return source.fetchChapterList(manga)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { syncChaptersWithSource(db, it, manga, source) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.source.base.OnlineSource
|
||||
import eu.kanade.tachiyomi.data.source.base.Source
|
||||
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
|
||||
import eu.kanade.tachiyomi.util.getResourceColor
|
||||
@@ -96,7 +97,7 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
||||
|
||||
// If manga source is known update source TextView.
|
||||
if (source != null) {
|
||||
manga_source.text = source.visibleName
|
||||
manga_source.text = source.toString()
|
||||
}
|
||||
|
||||
// Update genres TextView.
|
||||
@@ -140,8 +141,9 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
||||
* Open the manga in browser.
|
||||
*/
|
||||
fun openInBrowser() {
|
||||
val source = presenter.source as? OnlineSource ?: return
|
||||
try {
|
||||
val url = Uri.parse(presenter.source.baseUrl + presenter.manga.url)
|
||||
val url = Uri.parse(source.baseUrl + presenter.manga.url)
|
||||
val intent = CustomTabsIntent.Builder()
|
||||
.setToolbarColor(context.theme.getResourceColor(R.attr.colorPrimary))
|
||||
.build()
|
||||
|
||||
@@ -99,7 +99,7 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
|
||||
* @return manga information.
|
||||
*/
|
||||
private fun fetchMangaObs(): Observable<Manga> {
|
||||
return source.pullMangaFromNetwork(manga.url)
|
||||
return source.fetchMangaDetails(manga)
|
||||
.flatMap { networkManga ->
|
||||
manga.copyFrom(networkManga)
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
|
||||
@@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
|
||||
import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.source.SourceManager
|
||||
import eu.kanade.tachiyomi.data.source.base.OnlineSource
|
||||
import eu.kanade.tachiyomi.data.source.base.Source
|
||||
import eu.kanade.tachiyomi.data.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
@@ -126,9 +127,16 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
observable = Observable.from(ch.pages)
|
||||
.flatMap { downloadManager.getDownloadedImage(it, chapterDir) }
|
||||
} else {
|
||||
observable = source.getAllImageUrlsFromPageList(ch.pages)
|
||||
.flatMap({ source.getCachedImage(it) }, 2)
|
||||
.doOnCompleted { source.savePageList(ch.url, ch.pages) }
|
||||
observable = source.let { source ->
|
||||
if (source is OnlineSource) {
|
||||
source.fetchAllImageUrlsFromPageList(ch.pages)
|
||||
.flatMap({ source.getCachedImage(it) }, 2)
|
||||
.doOnCompleted { source.savePageList(ch, ch.pages) }
|
||||
} else {
|
||||
Observable.from(ch.pages)
|
||||
.flatMap { source.fetchImage(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
observable.doOnCompleted {
|
||||
if (!isSeamlessMode && chapter === ch) {
|
||||
@@ -139,13 +147,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
|
||||
// Listen por retry events
|
||||
add(retryPageSubject.observeOn(Schedulers.io())
|
||||
.flatMap { page ->
|
||||
if (page.imageUrl == null)
|
||||
source.getImageUrlFromPage(page)
|
||||
else
|
||||
Observable.just<Page>(page)
|
||||
}
|
||||
.flatMap { source.getCachedImage(it) }
|
||||
.flatMap { source.fetchImage(it) }
|
||||
.subscribe())
|
||||
}
|
||||
|
||||
@@ -156,7 +158,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
Observable.just(downloadManager.getSavedPageList(source, manga, chapter)!!)
|
||||
else
|
||||
// Fetch the page list from cache or fallback to network
|
||||
source.getCachedPageListOrPullFromNetwork(chapter.url)
|
||||
source.fetchPageList(chapter)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@@ -200,26 +202,15 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
|
||||
// Preload the first pages of the next chapter. Only for non seamless mode
|
||||
private fun getPreloadNextChapterObservable(): Observable<Page> {
|
||||
return source.getCachedPageListOrPullFromNetwork(nextChapter!!.url)
|
||||
val nextChapter = nextChapter ?: return Observable.error(Exception("No next chapter"))
|
||||
return source.fetchPageList(nextChapter)
|
||||
.flatMap { pages ->
|
||||
nextChapter!!.pages = pages
|
||||
nextChapter.pages = pages
|
||||
val pagesToPreload = Math.min(pages.size, 5)
|
||||
Observable.from(pages).take(pagesToPreload)
|
||||
}
|
||||
// Preload up to 5 images
|
||||
.concatMap { page ->
|
||||
if (page.imageUrl == null)
|
||||
source.getImageUrlFromPage(page)
|
||||
else
|
||||
Observable.just<Page>(page)
|
||||
}
|
||||
// Download the first image
|
||||
.concatMap { page ->
|
||||
if (page.pageNumber == 0)
|
||||
source.getCachedImage(page)
|
||||
else
|
||||
Observable.just<Page>(page)
|
||||
}
|
||||
.concatMap { source.fetchImage(it) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnCompleted { stopPreloadingNextChapter() }
|
||||
@@ -324,7 +315,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
|
||||
// Cache current page list progress for online chapters to allow a faster reopen
|
||||
if (!chapter.isDownloaded) {
|
||||
source.savePageList(chapter.url, pages)
|
||||
source.let { if (it is OnlineSource) it.savePageList(chapter, pages) }
|
||||
}
|
||||
|
||||
// Save current progress of the chapter. Mark as read if the chapter is finished
|
||||
@@ -382,7 +373,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
}
|
||||
|
||||
fun updateMangaSyncLastChapterRead() {
|
||||
for (mangaSync in mangaSyncList!!) {
|
||||
for (mangaSync in mangaSyncList ?: emptyList()) {
|
||||
val service = syncManager.getService(mangaSync.sync_id)
|
||||
if (service.isLogged && mangaSync.update) {
|
||||
UpdateMangaSyncService.start(context, mangaSync)
|
||||
@@ -417,16 +408,21 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
}
|
||||
|
||||
private fun preloadNextChapter() {
|
||||
if (hasNextChapter() && !isChapterDownloaded(nextChapter!!)) {
|
||||
start(PRELOAD_NEXT_CHAPTER)
|
||||
nextChapter?.let {
|
||||
if (!isChapterDownloaded(it)) {
|
||||
start(PRELOAD_NEXT_CHAPTER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopPreloadingNextChapter() {
|
||||
if (!isUnsubscribed(PRELOAD_NEXT_CHAPTER)) {
|
||||
stop(PRELOAD_NEXT_CHAPTER)
|
||||
if (nextChapter!!.pages != null)
|
||||
source.savePageList(nextChapter!!.url, nextChapter!!.pages)
|
||||
nextChapter?.let { chapter ->
|
||||
if (chapter.pages != null) {
|
||||
source.let { if (it is OnlineSource) it.savePageList(chapter, chapter.pages) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,11 @@ class SettingsSourcesFragment : SettingsNestedFragment() {
|
||||
.subscribe { languages ->
|
||||
sourcesPref.removeAll()
|
||||
|
||||
val enabledSources = settingsActivity.sourceManager.getSources()
|
||||
val enabledSources = settingsActivity.sourceManager.getOnlineSources()
|
||||
.filter { it.lang.code in languages }
|
||||
|
||||
for (source in enabledSources) {
|
||||
if (source.isLoginRequired) {
|
||||
if (source.isLoginRequired()) {
|
||||
val pref = createSource(source)
|
||||
sourcesPref.addPreference(pref)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class SettingsSourcesFragment : SettingsNestedFragment() {
|
||||
fun createSource(source: Source): Preference {
|
||||
return LoginPreference(preferenceManager.context).apply {
|
||||
key = preferences.keys.sourceUsername(source.id)
|
||||
title = source.visibleName
|
||||
title = source.toString()
|
||||
|
||||
setOnPreferenceClickListener {
|
||||
val fragment = SourceLoginDialog.newInstance(source)
|
||||
|
||||
Reference in New Issue
Block a user