From 4a64bb250dc81d69427f7a793b728be3157b75a0 Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Sat, 16 May 2020 17:53:02 -0400 Subject: [PATCH] Mitigate most of the lag problems, should fix all crashes(inspired by J2k code) Add tracking button the way J2K has it, my own implementation --- .../ui/manga/MangaAllInOneController.kt | 137 ++++---- .../ui/manga/MangaAllInOnePresenter.kt | 319 ++++++++---------- .../ui/manga/track/TrackController.kt | 15 +- .../manga_all_in_one_controller.xml | 28 +- .../layout/manga_all_in_one_controller.xml | 13 +- 5 files changed, 257 insertions(+), 255 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOneController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOneController.kt index 1b5062c50..17897f235 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOneController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOneController.kt @@ -22,8 +22,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.bumptech.glide.load.engine.DiskCacheStrategy import com.google.android.material.snackbar.Snackbar import com.google.gson.Gson -import com.jakewharton.rxrelay.BehaviorRelay -import com.jakewharton.rxrelay.PublishRelay import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter import eu.kanade.tachiyomi.R @@ -35,6 +33,7 @@ import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.glide.toMangaThumbnail import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.databinding.MangaAllInOneControllerBinding import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager @@ -56,6 +55,7 @@ import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter import eu.kanade.tachiyomi.ui.manga.chapter.DeleteChaptersDialog import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog +import eu.kanade.tachiyomi.ui.manga.track.TrackController import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.recent.history.HistoryController @@ -178,12 +178,8 @@ class MangaAllInOneController : private var initialLoad: Boolean = true - // EXH --> - private var lastMangaThumbnail: String? = null - // EXH --> val smartSearchConfig: SourceController.SmartSearchConfig? = args.getParcelable(SMART_SEARCH_CONFIG_EXTRA) - // EXH <-- override val coroutineContext: CoroutineContext = Job() + Dispatchers.Main @@ -192,12 +188,6 @@ class MangaAllInOneController : private val sourceManager: SourceManager by injectLazy() // EXH <-- - val lastUpdateRelay: BehaviorRelay = BehaviorRelay.create() - - val chapterCountRelay: BehaviorRelay = BehaviorRelay.create() - - val mangaFavoriteRelay: PublishRelay = PublishRelay.create() - val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false) var update = args.getBoolean(UPDATE_EXTRA, false) @@ -212,8 +202,7 @@ class MangaAllInOneController : override fun createPresenter(): MangaAllInOnePresenter { return MangaAllInOnePresenter( - manga!!, source!!, - chapterCountRelay, lastUpdateRelay, mangaFavoriteRelay, smartSearchConfig + this, manga!!, source!!, smartSearchConfig ) } @@ -232,6 +221,26 @@ class MangaAllInOneController : .onEach { onFavoriteClick() } .launchIn(scope) + if ((Injekt.get().hasLoggedServices()) && presenter.manga.favorite) { + binding.btnTracking.visible() + } + + scope.launch(Dispatchers.IO) { + if (Injekt.get().getTracks(presenter.manga).executeAsBlocking().any { + val status = Injekt.get().getService(it.sync_id)?.getStatus(it.status) + status != null + } + ) { + withContext(Dispatchers.Main) { + binding.btnTracking.icon = resources!!.getDrawable(R.drawable.ic_cloud_white_24dp, null) + } + } + } + + binding.btnTracking.clicks() + .onEach { openTracking() } + .launchIn(scope) + if (presenter.manga.favorite && presenter.getCategories().isNotEmpty()) { binding.btnCategories.visible() } @@ -440,6 +449,12 @@ class MangaAllInOneController : } // AZ <-- + private fun openTracking() { + router?.pushController( + TrackController(fromAllInOne = true, manga = manga).withFadeTransaction() + ) + } + /** * Check if manga is initialized. * If true update view with manga information, @@ -448,10 +463,10 @@ class MangaAllInOneController : * @param manga manga object containing information about manga. * @param source the source of the manga. */ - fun onNextManga(manga: Manga, source: Source) { + fun onNextManga(manga: Manga, source: Source, chapters: List) { if (manga.initialized) { // Update view. - setMangaInfo(manga, source) + setMangaInfo(manga, source, chapters) } else { // Initialize manga. fetchMangaFromSource() @@ -464,7 +479,7 @@ class MangaAllInOneController : * @param manga manga object containing information about manga. * @param source the source of the manga. */ - private fun setMangaInfo(manga: Manga, source: Source?) { + private fun setMangaInfo(manga: Manga, source: Source?, chapters: List) { val view = view ?: return // update full title TextView. @@ -579,6 +594,35 @@ class MangaAllInOneController : initialLoad = false } } + if (update || + // Auto-update old format galleries + ( + (presenter.manga.source == EH_SOURCE_ID || presenter.manga.source == EXH_SOURCE_ID) && + chapters.size == 1 && chapters.first().date_upload == 0L + ) + ) { + update = false + fetchMangaFromSource() + } + + val adapter = adapter ?: return + adapter.updateDataSet(chapters) + + if (selectedItems.isNotEmpty()) { + adapter.clearSelection() // we need to start from a clean state, index may have changed + createActionModeIfNeeded() + selectedItems.forEach { item -> + val position = adapter.indexOf(item) + if (position != -1 && !adapter.isSelected(position)) { + adapter.toggleSelection(position) + } + } + actionMode?.invalidate() + } + } + + fun setTracking() { + binding.btnTracking.icon = resources!!.getDrawable(R.drawable.ic_cloud_white_24dp, null) } private fun hideMangaInfo() { @@ -721,14 +765,7 @@ class MangaAllInOneController : presenter.fetchMangaFromSource(manualFetch) } - /** - * Update swipe refresh to stop showing refresh in progress spinner. - */ fun onFetchMangaDone() { - fetchChaptersFromSource() - } - - fun onFetchChaptersDone() { setRefreshing(false) } @@ -745,7 +782,7 @@ class MangaAllInOneController : * * @param value whether it should be refreshing or not. */ - private fun setRefreshing(value: Boolean) { + fun setRefreshing(value: Boolean) { binding.swipeRefresh.isRefreshing = value } @@ -999,56 +1036,6 @@ class MangaAllInOneController : return super.onOptionsItemSelected(item) } - fun onNextChapters(chapters: List) { - // If the list is empty, fetch chapters from source if the conditions are met - // We use presenter chapters instead because they are always unfiltered - if (presenter.chapters.isEmpty()) { - initialFetchChapters() - } - - if (update || - // Auto-update old format galleries - ( - (presenter.manga.source == EH_SOURCE_ID || presenter.manga.source == EXH_SOURCE_ID) && - chapters.size == 1 && chapters.first().date_upload == 0L - ) - ) { - update = false - fetchChaptersFromSource() - } - - val adapter = adapter ?: return - adapter.updateDataSet(chapters) - - if (selectedItems.isNotEmpty()) { - adapter.clearSelection() // we need to start from a clean state, index may have changed - createActionModeIfNeeded() - selectedItems.forEach { item -> - val position = adapter.indexOf(item) - if (position != -1 && !adapter.isSelected(position)) { - adapter.toggleSelection(position) - } - } - actionMode?.invalidate() - } - } - - private fun initialFetchChapters() { - // Only fetch if this view is from the catalog and it hasn't requested previously - if (fromSource && !presenter.hasRequested) { - fetchChaptersFromSource() - } - } - - private fun fetchChaptersFromSource() { - presenter.fetchChaptersFromSource() - } - - fun onFetchChaptersError(error: Throwable) { - onFetchChaptersDone() - activity?.toast(error.message) - } - fun onChapterStatusChange(download: Download) { getHolder(download.chapter)?.notifyStatus(download.status) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOnePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOnePresenter.kt index 0881a55a3..08696c3d6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOnePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaAllInOnePresenter.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.manga import android.os.Bundle import com.google.gson.Gson import com.jakewharton.rxrelay.BehaviorRelay -import com.jakewharton.rxrelay.PublishRelay import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category @@ -15,23 +14,27 @@ import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source +import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.browse.source.SourceController import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersPresenter import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed +import eu.kanade.tachiyomi.util.isLocal import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.removeCovers -import exh.EH_SOURCE_ID -import exh.EXH_SOURCE_ID import exh.MERGED_SOURCE_ID import exh.debug.DebugToggles import exh.eh.EHentaiUpdateHelper +import exh.isEhBasedSource import exh.util.await import java.util.Date +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import rx.Observable import rx.Subscription @@ -48,11 +51,9 @@ import uy.kohesive.injekt.injectLazy * Observable updates should be called from here. */ class MangaAllInOnePresenter( + val controller: MangaAllInOneController, val manga: Manga, val source: Source, - private val chapterCountRelay: BehaviorRelay, - private val lastUpdateRelay: BehaviorRelay, - private val mangaFavoriteRelay: PublishRelay, val smartSearchConfig: SourceController.SmartSearchConfig?, private val db: DatabaseHelper = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), @@ -67,11 +68,7 @@ class MangaAllInOnePresenter( var chapters: List = emptyList() private set - /** - * Subject of list of chapters to allow updating the view without going to DB. - */ - val chaptersRelay: PublishRelay> - by lazy { PublishRelay.create>() } + private val scope = CoroutineScope(Job() + Dispatchers.Default) /** * Whether the chapter list has been requested to the source. @@ -79,11 +76,6 @@ class MangaAllInOnePresenter( var hasRequested = false private set - /** - * Subscription to retrieve the new list of chapters from the source. - */ - private var fetchChaptersSubscription: Subscription? = null - /** * Subscription to observe download status changes. */ @@ -95,130 +87,136 @@ class MangaAllInOnePresenter( val redirectUserRelay = BehaviorRelay.create() // EXH <-- - /** - * Subscription to send the manga to the view. - */ - private var viewMangaSubscription: Subscription? = null - - /** - * Subscription to update the manga from the source. - */ - private var fetchMangaSubscription: Subscription? = null - override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) - getMangaObservable() - .subscribeLatestCache({ view, manga -> view.onNextManga(manga, source) }) + if (manga.isLocal()) { + controller.setRefreshing(true) + fetchMangaFromSource() + } else if (!manga.initialized) { + controller.setRefreshing(true) + fetchMangaFromSource() + } else { + updateManga() + } - // Update chapter count - chapterCountRelay.observeOn(AndroidSchedulers.mainThread()) - .subscribeLatestCache(MangaAllInOneController::setChapterCount) - - // Prepare the relay. - chaptersRelay.flatMap { applyChapterFilters(it) } - .observeOn(AndroidSchedulers.mainThread()) - .subscribeLatestCache(MangaAllInOneController::onNextChapters) { _, error -> Timber.e(error) } - - // Add the subscription that retrieves the chapters from the database, keeps subscribed to - // changes, and sends the list of chapters to the relay. - add( - db.getChapters(manga).asRxObservable() - .map { chapters -> - // Convert every chapter to a model. - chapters.map { it.toModel() } - } - .doOnNext { chapters -> - // Find downloaded chapters - setDownloadedChapters(chapters) - - // Store the last emission - this.chapters = chapters - - // Listen for download status changes - observeDownloads() - - // Emit the number of chapters to the info tab. - chapterCountRelay.call( - chapters.maxBy { it.chapter_number }?.chapter_number - ?: 0f - ) - - // Emit the upload date of the most recent chapter - lastUpdateRelay.call( - Date( - chapters.maxBy { it.date_upload }?.date_upload - ?: 0 - ) - ) - // EXH --> - if (chapters.isNotEmpty() && - (source.id == EXH_SOURCE_ID || source.id == EH_SOURCE_ID) && - DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled - ) { - // Check for gallery in library and accept manga with lowest id - // Find chapters sharing same root - add( - updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters) - .subscribeOn(Schedulers.io()) - .subscribe { (acceptedChain, _) -> - // Redirect if we are not the accepted root - if (manga.id != acceptedChain.manga.id) { - // Update if any of our chapters are not in accepted manga's chapters - val ourChapterUrls = chapters.map { it.url }.toSet() - val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet() - val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty() - redirectUserRelay.call( - ChaptersPresenter.EXHRedirect( - acceptedChain.manga, - update - ) - ) - } - } - ) - } - // EXH <-- - } - .subscribe { chaptersRelay.call(it) } - ) - - // Update favorite status - mangaFavoriteRelay.observeOn(AndroidSchedulers.mainThread()) - .subscribe { setFavorite(it) } - .apply { add(this) } - - // update last update date - lastUpdateRelay.observeOn(AndroidSchedulers.mainThread()) - .subscribeLatestCache(MangaAllInOneController::setLastUpdateDate) + // Listen for download status changes + observeDownloads() } - private fun getMangaObservable(): Observable { - return db.getManga(manga.url, manga.source).asRxObservable() - .observeOn(AndroidSchedulers.mainThread()) + private fun updateChapters() { + val chapters = db.getChapters(manga).executeAsBlocking().map { it.toModel() } + + // Find downloaded chapters + setDownloadedChapters(chapters) + + // EXH --> + if (chapters.isNotEmpty() && (source.isEhBasedSource()) && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) { + // Check for gallery in library and accept manga with lowest id + // Find chapters sharing same root + add( + updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters) + .subscribeOn(Schedulers.io()) + .subscribe { (acceptedChain, _) -> + // Redirect if we are not the accepted root + if (manga.id != acceptedChain.manga.id) { + // Update if any of our chapters are not in accepted manga's chapters + val ourChapterUrls = chapters.map { it.url }.toSet() + val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet() + val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty() + redirectUserRelay.call( + ChaptersPresenter.EXHRedirect( + acceptedChain.manga, + update + ) + ) + } + } + ) + } + // EXH <-- + + this.chapters = applyChapterFilters(chapters) + } + + private fun updateChapterInfo() { + scope.launch(Dispatchers.IO) { + val lastUpdateDate = Date( + chapters.maxBy { it.date_upload }?.date_upload ?: 0 + ) + + val chapterCount = chapters.maxBy { it.chapter_number }?.chapter_number ?: 0f + + withContext(Dispatchers.Main) { + // set chapter count + controller.setChapterCount(chapterCount) + // update last update date + controller.setLastUpdateDate(lastUpdateDate) + } + } + } + + private fun updateManga() { + scope.launch(Dispatchers.IO) { + val manga = db.getManga(manga.url, manga.source).executeAsBlocking()!! + updateChapters() + updateChapterInfo() + + withContext(Dispatchers.Main) { + controller.onNextManga( + manga, source, chapters + ) + } + } } /** * Fetch manga information from source. */ - fun fetchMangaFromSource(manualFetch: Boolean = false) { - if (!fetchMangaSubscription.isNullOrUnsubscribed()) return - fetchMangaSubscription = Observable.defer { source.fetchMangaDetails(manga) } - .map { networkManga -> - manga.prepUpdateCover(coverCache, networkManga, manualFetch) - manga.copyFrom(networkManga) - manga.initialized = true - db.insertManga(manga).executeAsBlocking() - manga + fun fetchMangaFromSource(manualFetch: Boolean = false, FetchManga: Boolean = true, FetchChapters: Boolean = true) { + hasRequested = true + + scope.launch(Dispatchers.IO) { + if (FetchManga) { + val networkManga = try { + source.fetchMangaDetails(manga).toBlocking().single() + } catch (e: Exception) { + withContext(Dispatchers.Main) { controller.onFetchMangaError(e) } + return@launch + } + if (networkManga != null) { + manga.prepUpdateCover(coverCache, networkManga, manualFetch) + manga.copyFrom(networkManga) + manga.initialized = true + db.insertManga(manga).executeAsBlocking() + } } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeFirst( - { view, _ -> - view.onFetchMangaDone() - }, - MangaAllInOneController::onFetchMangaError - ) + var chapters: List = listOf() + if (FetchChapters) { + try { + chapters = source.fetchChapterList(manga).toBlocking().single() + } catch (e: Exception) { + withContext(Dispatchers.Main) { controller.onFetchMangaError(e) } + return@launch + } + } + try { + if (FetchChapters) { + syncChaptersWithSource(db, chapters, manga, source) + + updateChapters() + updateChapterInfo() + } + withContext(Dispatchers.Main) { + controller.onNextManga(this@MangaAllInOnePresenter.manga, this@MangaAllInOnePresenter.source, this@MangaAllInOnePresenter.chapters) + controller.onFetchMangaDone() + } + } catch (e: java.lang.Exception) { + withContext(Dispatchers.Main) { + controller.onFetchMangaError(e) + } + } + } } /** @@ -404,49 +402,23 @@ class MangaAllInOnePresenter( } } - /** - * Requests an updated list of chapters from the source. - */ - fun fetchChaptersFromSource() { - hasRequested = true - - if (!fetchChaptersSubscription.isNullOrUnsubscribed()) return - fetchChaptersSubscription = Observable.defer { source.fetchChapterList(manga) } - .subscribeOn(Schedulers.io()) - .map { syncChaptersWithSource(db, it, manga, source) } - .observeOn(AndroidSchedulers.mainThread()) - .subscribeFirst( - { view, _ -> - view.onFetchChaptersDone() - }, - MangaAllInOneController::onFetchChaptersError - ) - } - - /** - * Updates the UI after applying the filters. - */ - private fun refreshChapters() { - chaptersRelay.call(chapters) - } - /** * Applies the view filters to the list of chapters obtained from the database. * @param chapters the list of chapters from the database * @return an observable of the list of chapters filtered and sorted. */ - private fun applyChapterFilters(chapters: List): Observable> { - var observable = Observable.from(chapters).subscribeOn(Schedulers.io()) + private fun applyChapterFilters(chapterList: List): List { + var chapters = chapterList if (onlyUnread()) { - observable = observable.filter { !it.read } + chapters = chapters.filter { !it.read } } else if (onlyRead()) { - observable = observable.filter { it.read } + chapters = chapters.filter { it.read } } if (onlyDownloaded()) { - observable = observable.filter { it.isDownloaded || it.manga.source == LocalSource.ID } + chapters = chapters.filter { it.isDownloaded || it.manga.source == LocalSource.ID } } if (onlyBookmarked()) { - observable = observable.filter { it.bookmark } + chapters = chapters.filter { it.bookmark } } val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) { Manga.SORTING_SOURCE -> when (sortDescending()) { @@ -457,9 +429,10 @@ class MangaAllInOnePresenter( true -> { c1, c2 -> c2.chapter_number.compareTo(c1.chapter_number) } false -> { c1, c2 -> c1.chapter_number.compareTo(c2.chapter_number) } } - else -> throw NotImplementedError("Unimplemented sorting method") + else -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) } } - return observable.toSortedList(sortFunction) + chapters = chapters.sortedWith(Comparator(sortFunction)) + return chapters } /** @@ -478,7 +451,7 @@ class MangaAllInOnePresenter( // Force UI update if downloaded filter active and download finished. if (onlyDownloaded() && download.status == Download.DOWNLOADED) { - refreshChapters() + updateChapters() } } @@ -541,7 +514,7 @@ class MangaAllInOnePresenter( fun deleteChapters(chapters: List) { Observable.just(chapters) .doOnNext { deleteChaptersInternal(chapters) } - .doOnNext { if (onlyDownloaded()) refreshChapters() } + .doOnNext { if (onlyDownloaded()) updateChapters() } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeFirst( @@ -570,7 +543,7 @@ class MangaAllInOnePresenter( fun revertSortOrder() { manga.setChapterOrder(if (sortDescending()) Manga.SORT_ASC else Manga.SORT_DESC) db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** @@ -580,7 +553,7 @@ class MangaAllInOnePresenter( fun setUnreadFilter(onlyUnread: Boolean) { manga.readFilter = if (onlyUnread) Manga.SHOW_UNREAD else Manga.SHOW_ALL db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** @@ -590,7 +563,7 @@ class MangaAllInOnePresenter( fun setReadFilter(onlyRead: Boolean) { manga.readFilter = if (onlyRead) Manga.SHOW_READ else Manga.SHOW_ALL db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** @@ -600,7 +573,7 @@ class MangaAllInOnePresenter( fun setDownloadedFilter(onlyDownloaded: Boolean) { manga.downloadedFilter = if (onlyDownloaded) Manga.SHOW_DOWNLOADED else Manga.SHOW_ALL db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** @@ -610,7 +583,7 @@ class MangaAllInOnePresenter( fun setBookmarkedFilter(onlyBookmarked: Boolean) { manga.bookmarkedFilter = if (onlyBookmarked) Manga.SHOW_BOOKMARKED else Manga.SHOW_ALL db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** @@ -621,14 +594,14 @@ class MangaAllInOnePresenter( manga.downloadedFilter = Manga.SHOW_ALL manga.bookmarkedFilter = Manga.SHOW_ALL db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** * Adds manga to library */ fun addToLibrary() { - mangaFavoriteRelay.call(true) + setFavorite(true) } /** @@ -647,7 +620,7 @@ class MangaAllInOnePresenter( fun setSorting(sort: Int) { manga.sorting = sort db.updateFlags(manga).executeAsBlocking() - refreshChapters() + updateChapters() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackController.kt index d7e0824c6..de3c112d8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackController.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.databinding.TrackControllerBinding import eu.kanade.tachiyomi.ui.base.controller.NucleusController @@ -17,7 +18,7 @@ import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.swiperefreshlayout.refreshes import timber.log.Timber -class TrackController : +class TrackController(val fromAllInOne: Boolean = false, val manga: Manga? = null) : NucleusController(), TrackAdapter.OnClickListener, SetTrackStatusDialog.Listener, @@ -34,7 +35,13 @@ class TrackController : } override fun createPresenter(): TrackPresenter { - return TrackPresenter((parentController as MangaController).manga!!) + return ( + if (fromAllInOne && manga != null) { + TrackPresenter(manga) + } else { + TrackPresenter((parentController as MangaController).manga!!) + } + ) } override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { @@ -63,7 +70,9 @@ class TrackController : val atLeastOneLink = trackings.any { it.track != null } adapter?.items = trackings binding.swipeRefresh.isEnabled = atLeastOneLink - (parentController as? MangaController)?.setTrackingIcon(atLeastOneLink) + if (!fromAllInOne) { + (parentController as? MangaController)?.setTrackingIcon(atLeastOneLink) + } } fun onSearchResults(results: List) { diff --git a/app/src/main/res/layout-land/manga_all_in_one_controller.xml b/app/src/main/res/layout-land/manga_all_in_one_controller.xml index edeca5d84..64960d5dd 100644 --- a/app/src/main/res/layout-land/manga_all_in_one_controller.xml +++ b/app/src/main/res/layout-land/manga_all_in_one_controller.xml @@ -204,16 +204,25 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/manga_source_label" /> + + + app:layout_constraintTop_toBottomOf="parent"> + + + + + app:layout_constraintTop_toBottomOf="@+id/actions_bar_scroll_view" /> + +