Address coroutine scope leaks for SY

This commit is contained in:
Jobobby04 2021-01-07 23:12:13 -05:00
parent 3683665e8a
commit fca7dad7b0
32 changed files with 217 additions and 384 deletions

View File

@ -1,9 +1,9 @@
package eu.kanade.tachiyomi.source.online package eu.kanade.tachiyomi.source.online
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController
interface BrowseSourceFilterHeader : CatalogueSource { interface BrowseSourceFilterHeader : CatalogueSource {
fun getFilterHeader(controller: Controller): RecyclerView.Adapter<*> fun getFilterHeader(controller: BaseController<*>): RecyclerView.Adapter<*>
} }

View File

@ -5,7 +5,6 @@ import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -27,6 +26,7 @@ import eu.kanade.tachiyomi.source.online.LoginSource
import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.RandomMangaSource import eu.kanade.tachiyomi.source.online.RandomMangaSource
import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.source.online.UrlImportableSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.lang.asObservable import eu.kanade.tachiyomi.util.lang.asObservable
@ -267,7 +267,7 @@ class MangaDex(delegate: HttpSource, val context: Context) :
return withContext(Dispatchers.IO) { FollowsHandler(client, headers, Injekt.get(), useLowQualityThumbnail()).updateFollowStatus(mangaID, followStatus) } return withContext(Dispatchers.IO) { FollowsHandler(client, headers, Injekt.get(), useLowQualityThumbnail()).updateFollowStatus(mangaID, followStatus) }
} }
override fun getFilterHeader(controller: Controller): MangaDexFabHeaderAdapter { override fun getFilterHeader(controller: BaseController<*>): MangaDexFabHeaderAdapter {
return MangaDexFabHeaderAdapter(controller, this) return MangaDexFabHeaderAdapter(controller, this)
} }

View File

@ -17,20 +17,10 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding import eu.kanade.tachiyomi.databinding.MigrationBottomSheetBinding
import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener: StartMigrationListener) : BottomSheetDialog(activity, theme) { class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val listener: StartMigrationListener) : BottomSheetDialog(activity, theme) {
/** private val preferences: PreferencesHelper by injectLazy()
* Preferences helper.
*/
private val preferences by injectLazy<PreferencesHelper>()
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private val binding: MigrationBottomSheetBinding = MigrationBottomSheetBinding.inflate(activity.layoutInflater) private val binding: MigrationBottomSheetBinding = MigrationBottomSheetBinding.inflate(activity.layoutInflater)
@ -50,7 +40,7 @@ class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val lis
initPreferences() initPreferences()
binding.fab.clicks().onEach { binding.fab.setOnClickListener {
preferences.skipPreMigration().set(binding.skipStep.isChecked) preferences.skipPreMigration().set(binding.skipStep.isChecked)
listener.startMigration( listener.startMigration(
if (binding.useSmartSearch.isChecked && binding.extraSearchParamText.text.isNotBlank()) { if (binding.useSmartSearch.isChecked && binding.extraSearchParamText.text.isNotBlank()) {
@ -58,7 +48,7 @@ class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val lis
} else null } else null
) )
dismiss() dismiss()
}.launchIn(scope) }
} }
/** /**
@ -75,7 +65,7 @@ class MigrationBottomSheetDialog(activity: Activity, theme: Int, private val lis
binding.migChapters.setOnCheckedChangeListener { _, _ -> setFlags() } binding.migChapters.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migCategories.setOnCheckedChangeListener { _, _ -> setFlags() } binding.migCategories.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migTracking.setOnCheckedChangeListener { _, _ -> setFlags() } binding.migTracking.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.migExtra.setOnCheckedChangeListener { buttonView, isChecked -> setFlags() } binding.migExtra.setOnCheckedChangeListener { _, _ -> setFlags() }
binding.useSmartSearch.bindToPreference(preferences.smartMigration()) binding.useSmartSearch.bindToPreference(preferences.smartMigration())
binding.extraSearchParamText.isVisible = false binding.extraSearchParamText.isVisible = false

View File

@ -27,9 +27,6 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListController import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationListController
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationProcedureConfig import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigrationProcedureConfig
import eu.kanade.tachiyomi.util.view.shrinkOnScroll import eu.kanade.tachiyomi.util.view.shrinkOnScroll
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class PreMigrationController(bundle: Bundle? = null) : class PreMigrationController(bundle: Bundle? = null) :
@ -44,8 +41,6 @@ class PreMigrationController(bundle: Bundle? = null) :
private val config: LongArray = args.getLongArray(MANGA_IDS_EXTRA) ?: LongArray(0) private val config: LongArray = args.getLongArray(MANGA_IDS_EXTRA) ?: LongArray(0)
val scope = CoroutineScope(Job() + Dispatchers.Main)
private var actionFab: ExtendedFloatingActionButton? = null private var actionFab: ExtendedFloatingActionButton? = null
private var actionFabScrollListener: RecyclerView.OnScrollListener? = null private var actionFabScrollListener: RecyclerView.OnScrollListener? = null

View File

@ -66,8 +66,6 @@ class MigrationListController(bundle: Bundle? = null) :
private var adapter: MigrationProcessAdapter? = null private var adapter: MigrationProcessAdapter? = null
val scope = CoroutineScope(Job() + Dispatchers.Default)
val config: MigrationProcedureConfig? = args.getParcelable(CONFIG_EXTRA) val config: MigrationProcedureConfig? = args.getParcelable(CONFIG_EXTRA)
private val db: DatabaseHelper by injectLazy() private val db: DatabaseHelper by injectLazy()
@ -89,7 +87,7 @@ class MigrationListController(bundle: Bundle? = null) :
return binding.root return binding.root
} }
override fun getTitle(): String? { override fun getTitle(): String {
return resources?.getString(R.string.migration) + " (${adapter?.items?.count { return resources?.getString(R.string.migration) + " (${adapter?.items?.count {
it.manga.migrationStatus != MigrationStatus.RUNNING it.manga.migrationStatus != MigrationStatus.RUNNING
}}/${adapter?.itemCount ?: 0})" }}/${adapter?.itemCount ?: 0})"
@ -102,7 +100,7 @@ class MigrationListController(bundle: Bundle? = null) :
val newMigratingManga = migratingManga ?: run { val newMigratingManga = migratingManga ?: run {
val new = config.mangaIds.map { val new = config.mangaIds.map {
MigratingManga(db, sourceManager, it, scope.coroutineContext) MigratingManga(db, sourceManager, it, viewScope.coroutineContext + Dispatchers.IO)
} }
migratingManga = new.toMutableList() migratingManga = new.toMutableList()
new new
@ -117,7 +115,7 @@ class MigrationListController(bundle: Bundle? = null) :
adapter?.updateDataSet(newMigratingManga.map { it.toModal() }) adapter?.updateDataSet(newMigratingManga.map { it.toModal() })
if (migrationsJob == null) { if (migrationsJob == null) {
migrationsJob = scope.launch { migrationsJob = viewScope.launch(Dispatchers.IO) {
runMigrations(newMigratingManga) runMigrations(newMigratingManga)
} }
} }

View File

@ -22,14 +22,11 @@ import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.setVectorCompat import eu.kanade.tachiyomi.util.view.setVectorCompat
import exh.MERGED_SOURCE_ID import exh.MERGED_SOURCE_ID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import reactivecircus.flowbinding.android.view.clicks import reactivecircus.flowbinding.android.view.clicks
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat import java.text.DecimalFormat
@ -41,7 +38,6 @@ class MigrationProcessHolder(
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
private var item: MigrationProcessItem? = null private var item: MigrationProcessItem? = null
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private val binding = MigrationProcessItemBinding.bind(view) private val binding = MigrationProcessItemBinding.bind(view)
init { init {
@ -84,7 +80,7 @@ class MigrationProcessHolder(
true true
).withFadeTransaction() ).withFadeTransaction()
) )
}.launchIn(scope) }.launchIn(adapter.controller.viewScope)
} }
/*launchUI { /*launchUI {
@ -120,7 +116,7 @@ class MigrationProcessHolder(
true true
).withFadeTransaction() ).withFadeTransaction()
) )
}.launchIn(scope) }.launchIn(adapter.controller.viewScope)
} else { } else {
binding.migrationMangaCardTo.loadingGroup.isVisible = false binding.migrationMangaCardTo.loadingGroup.isVisible = false
binding.migrationMangaCardTo.title.text = view.context.applicationContext binding.migrationMangaCardTo.title.text = view.context.applicationContext

View File

@ -9,7 +9,6 @@ import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bluelinelabs.conductor.Controller
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -17,6 +16,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.online.BrowseSourceFilterHeader import eu.kanade.tachiyomi.source.online.BrowseSourceFilterHeader
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.widget.SimpleNavigationView import eu.kanade.tachiyomi.widget.SimpleNavigationView
import exh.savedsearches.EXHSavedSearch import exh.savedsearches.EXHSavedSearch
import exh.source.getMainSource import exh.source.getMainSource
@ -24,7 +24,7 @@ import exh.source.getMainSource
class SourceFilterSheet( class SourceFilterSheet(
activity: Activity, activity: Activity,
// SY --> // SY -->
controller: Controller, controller: BaseController<*>,
source: CatalogueSource, source: CatalogueSource,
searches: List<EXHSavedSearch> = emptyList(), searches: List<EXHSavedSearch> = emptyList(),
// SY <-- // SY <--
@ -72,7 +72,7 @@ class SourceFilterSheet(
} }
// SY <-- // SY <--
class FilterNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null /* SY --> */, searches: List<EXHSavedSearch> = emptyList(), source: CatalogueSource? = null, controller: Controller? = null/* SY <-- */) : class FilterNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null /* SY --> */, searches: List<EXHSavedSearch> = emptyList(), source: CatalogueSource? = null, controller: BaseController<*>? = null/* SY <-- */) :
SimpleNavigationView(context, attrs) { SimpleNavigationView(context, attrs) {
var onFilterClicked = {} var onFilterClicked = {}

View File

@ -8,12 +8,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.IndexAdapterBinding import eu.kanade.tachiyomi.databinding.IndexAdapterBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
/** /**
* Adapter that holds the search cards. * Adapter that holds the search cards.
@ -26,7 +20,6 @@ class IndexAdapter(val controller: IndexController) :
val clickListener: ClickListener = controller val clickListener: ClickListener = controller
private lateinit var binding: IndexAdapterBinding private lateinit var binding: IndexAdapterBinding
private val scope = CoroutineScope(Job() + Dispatchers.Main)
var holder: IndexAdapter.ViewHolder? = null var holder: IndexAdapter.ViewHolder? = null
@ -50,16 +43,12 @@ class IndexAdapter(val controller: IndexController) :
private var browseLastBoundResults: List<IndexCardItem>? = null private var browseLastBoundResults: List<IndexCardItem>? = null
init { init {
binding.browseBarWrapper.clicks() binding.browseBarWrapper.setOnClickListener {
.onEach { clickListener.onBrowseClick()
clickListener.onBrowseClick() }
} binding.latestBarWrapper.setOnClickListener {
.launchIn(scope) clickListener.onLatestClick()
binding.latestBarWrapper.clicks() }
.onEach {
clickListener.onLatestClick()
}
.launchIn(scope)
binding.latestRecycler.layoutManager = LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false) binding.latestRecycler.layoutManager = LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false)
binding.latestRecycler.adapter = latestAdapter binding.latestRecycler.adapter = latestAdapter

View File

@ -17,9 +17,7 @@ import eu.kanade.tachiyomi.util.lang.asFlow
import eu.kanade.tachiyomi.util.lang.runAsObservable import eu.kanade.tachiyomi.util.lang.runAsObservable
import exh.savedsearches.EXHSavedSearch import exh.savedsearches.EXHSavedSearch
import exh.savedsearches.JsonSavedSearch import exh.savedsearches.JsonSavedSearch
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.singleOrNull import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -55,8 +53,6 @@ open class IndexPresenter(
*/ */
private var fetchSourcesSubscription: Subscription? = null private var fetchSourcesSubscription: Subscription? = null
private val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Query from the view. * Query from the view.
*/ */
@ -102,7 +98,7 @@ open class IndexPresenter(
// Create image fetch subscription // Create image fetch subscription
initializeFetchImageSubscription() initializeFetchImageSubscription()
scope.launch(Dispatchers.IO) { presenterScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Observable.just(null).subscribeLatestCache({ view, results -> Observable.just(null).subscribeLatestCache({ view, results ->
view.setLatestManga(results) view.setLatestManga(results)
@ -130,7 +126,7 @@ open class IndexPresenter(
} }
} }
scope.launch(Dispatchers.IO) { presenterScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Observable.just(null).subscribeLatestCache({ view, results -> Observable.just(null).subscribeLatestCache({ view, results ->
view.setBrowseManga(results) view.setBrowseManga(results)

View File

@ -5,9 +5,6 @@ import com.elvishew.xlog.XLog
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.plusAssign import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import rx.Observable import rx.Observable
@ -29,8 +26,6 @@ class BiometricTimesPresenter : BasePresenter<BiometricTimesController>() {
val preferences: PreferencesHelper = Injekt.get() val preferences: PreferencesHelper = Injekt.get()
val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Called when the presenter is created. * Called when the presenter is created.
* *
@ -47,7 +42,7 @@ class BiometricTimesPresenter : BasePresenter<BiometricTimesController>() {
.map { it.map(::BiometricTimesItem) } .map { it.map(::BiometricTimesItem) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(BiometricTimesController::setBiometricTimeItems) .subscribeLatestCache(BiometricTimesController::setBiometricTimeItems)
}.launchIn(scope) }.launchIn(presenterScope)
} }
/** /**

View File

@ -5,9 +5,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.minusAssign import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import rx.Observable import rx.Observable
@ -27,8 +24,6 @@ class SortTagPresenter : BasePresenter<SortTagController>() {
val preferences: PreferencesHelper = Injekt.get() val preferences: PreferencesHelper = Injekt.get()
val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Called when the presenter is created. * Called when the presenter is created.
* *
@ -46,7 +41,7 @@ class SortTagPresenter : BasePresenter<SortTagController>() {
.map { tagPairs -> tagPairs.map { it.second }.map(::SortTagItem) } .map { tagPairs -> tagPairs.map { it.second }.map(::SortTagItem) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(SortTagController::setCategories) .subscribeLatestCache(SortTagController::setCategories)
}.launchIn(scope) }.launchIn(presenterScope)
} }
/** /**

View File

@ -3,9 +3,6 @@ package eu.kanade.tachiyomi.ui.category.repos
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import rx.Observable import rx.Observable
@ -19,8 +16,6 @@ import uy.kohesive.injekt.api.get
class RepoPresenter( class RepoPresenter(
private val preferences: PreferencesHelper = Injekt.get() private val preferences: PreferencesHelper = Injekt.get()
) : BasePresenter<RepoController>() { ) : BasePresenter<RepoController>() {
val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* List containing repos. * List containing repos.
*/ */
@ -41,7 +36,7 @@ class RepoPresenter(
.map { it.map(::RepoItem) } .map { it.map(::RepoItem) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(RepoController::setRepos) .subscribeLatestCache(RepoController::setRepos)
}.launchIn(scope) }.launchIn(presenterScope)
} }
/** /**

View File

@ -4,9 +4,6 @@ import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import rx.Observable import rx.Observable
@ -28,8 +25,6 @@ class SourceCategoryPresenter(
val preferences: PreferencesHelper = Injekt.get() val preferences: PreferencesHelper = Injekt.get()
val scope = CoroutineScope(Job() + Dispatchers.Main)
/** /**
* Called when the presenter is created. * Called when the presenter is created.
* *
@ -45,7 +40,7 @@ class SourceCategoryPresenter(
.map { it.map(::SourceCategoryItem) } .map { it.map(::SourceCategoryItem) }
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(SourceCategoryController::setCategories) .subscribeLatestCache(SourceCategoryController::setCategories)
}.launchIn(scope) }.launchIn(presenterScope)
} }
/** /**

View File

@ -738,5 +738,10 @@ class LibraryPresenter(
return map to categories return map to categories
} }
override fun onDestroy() {
super.onDestroy()
favoritesSync.onDestroy()
}
// SY <-- // SY <--
} }

View File

@ -57,8 +57,6 @@ import exh.metadata.metadata.base.insertFlatMetadata
import exh.source.getMainSource import exh.source.getMainSource
import exh.util.shouldDeleteChapters import exh.util.shouldDeleteChapters
import exh.util.trimOrNull import exh.util.trimOrNull
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@ -88,8 +86,6 @@ class MangaPresenter(
private val sourceManager: SourceManager = Injekt.get() private val sourceManager: SourceManager = Injekt.get()
) : BasePresenter<MangaController>() { ) : BasePresenter<MangaController>() {
val scope = CoroutineScope(Job() + Dispatchers.IO)
/** /**
* Subscription to update the manga from the source. * Subscription to update the manga from the source.
*/ */
@ -236,7 +232,7 @@ class MangaPresenter(
) )
) )
} }
}.launchIn(scope) }.launchIn(presenterScope)
} }
// SY <-- // SY <--
} }

View File

@ -71,15 +71,15 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.SimpleAnimationListener import eu.kanade.tachiyomi.widget.SimpleAnimationListener
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
import exh.util.defaultReaderType import exh.util.defaultReaderType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.sample import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import nucleus.factory.RequiresPresenter import nucleus.factory.RequiresPresenter
import reactivecircus.flowbinding.android.view.clicks import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.widget.checkedChanges import reactivecircus.flowbinding.android.widget.checkedChanges
@ -122,7 +122,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
// SY --> // SY -->
private var ehUtilsVisible = false private var ehUtilsVisible = false
private var autoscrollScope: CoroutineScope = CoroutineScope(Job() + Dispatchers.Main) private val autoScrollFlow = MutableSharedFlow<Unit>()
private var autoScrollJob: Job? = null private var autoScrollJob: Job? = null
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
@ -219,19 +219,12 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
if (interval == -1.0) return if (interval == -1.0) return
val duration = interval.seconds val duration = interval.seconds
autoScrollJob = autoScrollJob = lifecycleScope.launch(Dispatchers.IO) {
flow { while (true) {
while (true) { delay(duration)
delay(duration) autoScrollFlow.emit(Unit)
emit(Unit)
}
}.onEach {
viewer.let { v ->
if (v is PagerViewer) v.moveToNext()
else if (v is WebtoonViewer) v.scrollDown()
}
} }
.launchIn(autoscrollScope) }
} }
// SY <-- // SY <--
@ -591,6 +584,15 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
} }
} }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
autoScrollFlow
.onEach {
viewer.let { v ->
if (v is PagerViewer) v.moveToNext()
else if (v is WebtoonViewer) v.scrollDown()
}
}
.launchIn(lifecycleScope)
// <-- EH // <-- EH
// Set initial visibility // Set initial visibility

View File

@ -30,6 +30,7 @@ import exh.util.wifiManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.FormBody import okhttp3.FormBody
@ -418,6 +419,10 @@ class FavoritesSyncHelper(val context: Context) {
class IgnoredException : RuntimeException() class IgnoredException : RuntimeException()
fun onDestroy() {
scope.cancel()
}
companion object { companion object {
private const val THROTTLE_WARN = 1000 private const val THROTTLE_WARN = 1000
} }

View File

@ -4,27 +4,22 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.databinding.SourceFilterMangadexHeaderBinding import eu.kanade.tachiyomi.databinding.SourceFilterMangadexHeaderBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.online.RandomMangaSource import eu.kanade.tachiyomi.source.online.RandomMangaSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
import exh.md.follows.MangaDexFollowsController import exh.md.follows.MangaDexFollowsController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks import reactivecircus.flowbinding.android.view.clicks
class MangaDexFabHeaderAdapter(val controller: Controller, val source: CatalogueSource) : class MangaDexFabHeaderAdapter(val controller: BaseController<*>, val source: CatalogueSource) :
RecyclerView.Adapter<MangaDexFabHeaderAdapter.SavedSearchesViewHolder>() { RecyclerView.Adapter<MangaDexFabHeaderAdapter.SavedSearchesViewHolder>() {
private lateinit var binding: SourceFilterMangadexHeaderBinding private lateinit var binding: SourceFilterMangadexHeaderBinding
private val scope = CoroutineScope(Job() + Dispatchers.Main)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedSearchesViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedSearchesViewHolder {
binding = SourceFilterMangadexHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false) binding = SourceFilterMangadexHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SavedSearchesViewHolder(binding.root) return SavedSearchesViewHolder(binding.root)
@ -38,18 +33,15 @@ class MangaDexFabHeaderAdapter(val controller: Controller, val source: Catalogue
inner class SavedSearchesViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class SavedSearchesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind() { fun bind() {
binding.mangadexFollows.clicks() binding.mangadexFollows.setOnClickListener {
.onEach { controller.router.replaceTopController(MangaDexFollowsController(source).withFadeTransaction())
controller.router.replaceTopController(MangaDexFollowsController(source).withFadeTransaction()) }
}
.launchIn(scope)
binding.mangadexRandom.clicks() binding.mangadexRandom.clicks()
.onEach { .onEach {
(source as? RandomMangaSource)?.fetchRandomMangaUrl()?.let { randomMangaId -> (source as? RandomMangaSource)?.fetchRandomMangaUrl()?.let { randomMangaId ->
controller.router.replaceTopController(BrowseSourceController(source, randomMangaId).withFadeTransaction()) controller.router.replaceTopController(BrowseSourceController(source, randomMangaId).withFadeTransaction())
} }
} }.launchIn(controller.viewScope)
.launchIn(scope)
} }
} }
} }

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -59,6 +60,11 @@ class ConfiguringDialogController : DialogController() {
materialDialog = null materialDialog = null
} }
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) { override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState) super.onRestoreInstanceState(savedInstanceState)
finish() finish()

View File

@ -11,9 +11,7 @@ import exh.GalleryAddEvent
import exh.GalleryAdder import exh.GalleryAdder
import exh.util.trimOrNull import exh.util.trimOrNull
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -23,7 +21,6 @@ import uy.kohesive.injekt.api.get
class BatchAddPresenter : BasePresenter<BatchAddController>() { class BatchAddPresenter : BasePresenter<BatchAddController>() {
private val galleryAdder by lazy { GalleryAdder() } private val galleryAdder by lazy { GalleryAdder() }
private val scope = CoroutineScope(Job() + Dispatchers.Main)
val progressTotalRelay = BehaviorRelay.create(0)!! val progressTotalRelay = BehaviorRelay.create(0)!!
val progressRelay = BehaviorRelay.create(0)!! val progressRelay = BehaviorRelay.create(0)!!
@ -62,7 +59,7 @@ class BatchAddPresenter : BasePresenter<BatchAddController>() {
XLog.tag("BatchAddPresenter").enableStackTrace(2).e(throwable) XLog.tag("BatchAddPresenter").enableStackTrace(2).e(throwable)
} }
scope.launch(Dispatchers.IO + handler) { presenterScope.launch(Dispatchers.IO + handler) {
val succeeded = mutableListOf<String>() val succeeded = mutableListOf<String>()
val failed = mutableListOf<String>() val failed = mutableListOf<String>()

View File

@ -6,18 +6,11 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.databinding.MetadataViewItemBinding import eu.kanade.tachiyomi.databinding.MetadataViewItemBinding
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
class MetadataViewAdapter(private var data: List<Pair<String, String>>) : class MetadataViewAdapter(private var data: List<Pair<String, String>>) :
RecyclerView.Adapter<MetadataViewAdapter.ViewHolder>() { RecyclerView.Adapter<MetadataViewAdapter.ViewHolder>() {
private lateinit var binding: MetadataViewItemBinding private lateinit var binding: MetadataViewItemBinding
private val scope = CoroutineScope(Job() + Dispatchers.Main)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MetadataViewAdapter.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MetadataViewAdapter.ViewHolder {
binding = MetadataViewItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) binding = MetadataViewItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
@ -42,11 +35,9 @@ class MetadataViewAdapter(private var data: List<Pair<String, String>>) :
fun bind(position: Int) { fun bind(position: Int) {
binding.infoTitle.text = data[position].first binding.infoTitle.text = data[position].first
binding.infoText.text = data[position].second binding.infoText.text = data[position].second
binding.infoText.clicks() binding.infoText.setOnClickListener {
.onEach { itemView.context.copyToClipboard(data[position].second, data[position].second)
itemView.context.copyToClipboard(data[position].second, data[position].second) }
}
.launchIn(scope)
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -14,20 +14,12 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
class EHentaiDescriptionAdapter( class EHentaiDescriptionAdapter(
private val controller: MangaController private val controller: MangaController
) : ) :
RecyclerView.Adapter<EHentaiDescriptionAdapter.EHentaiDescriptionViewHolder>() { RecyclerView.Adapter<EHentaiDescriptionAdapter.EHentaiDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterEhBinding private lateinit var binding: DescriptionAdapterEhBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EHentaiDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EHentaiDescriptionViewHolder {
@ -87,25 +79,22 @@ class EHentaiDescriptionAdapter(
binding.uploader, binding.uploader,
binding.visible binding.visible
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -12,20 +12,12 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.EightMusesSearchMetadata import exh.metadata.metadata.EightMusesSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
class EightMusesDescriptionAdapter( class EightMusesDescriptionAdapter(
private val controller: MangaController private val controller: MangaController
) : ) :
RecyclerView.Adapter<EightMusesDescriptionAdapter.EightMusesDescriptionViewHolder>() { RecyclerView.Adapter<EightMusesDescriptionAdapter.EightMusesDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapter8mBinding private lateinit var binding: DescriptionAdapter8mBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EightMusesDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EightMusesDescriptionViewHolder {
@ -48,24 +40,21 @@ class EightMusesDescriptionAdapter(
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp) binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
binding.title.longClicks() binding.title.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( binding.title.text.toString(),
binding.title.text.toString(), binding.title.text.toString()
binding.title.text.toString() )
) true
} }
.launchIn(scope)
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -12,20 +12,12 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.HBrowseSearchMetadata import exh.metadata.metadata.HBrowseSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
class HBrowseDescriptionAdapter( class HBrowseDescriptionAdapter(
private val controller: MangaController private val controller: MangaController
) : ) :
RecyclerView.Adapter<HBrowseDescriptionAdapter.HBrowseDescriptionViewHolder>() { RecyclerView.Adapter<HBrowseDescriptionAdapter.HBrowseDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterHbBinding private lateinit var binding: DescriptionAdapterHbBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HBrowseDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HBrowseDescriptionViewHolder {
@ -49,24 +41,21 @@ class HBrowseDescriptionAdapter(
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp) binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
binding.pages.longClicks() binding.pages.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( binding.pages.text.toString(),
binding.pages.text.toString(), binding.pages.text.toString()
binding.pages.text.toString() )
) true
} }
.launchIn(scope)
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -12,20 +12,12 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.HentaiCafeSearchMetadata import exh.metadata.metadata.HentaiCafeSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
class HentaiCafeDescriptionAdapter( class HentaiCafeDescriptionAdapter(
private val controller: MangaController private val controller: MangaController
) : ) :
RecyclerView.Adapter<HentaiCafeDescriptionAdapter.HentaiCafeDescriptionViewHolder>() { RecyclerView.Adapter<HentaiCafeDescriptionAdapter.HentaiCafeDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterHcBinding private lateinit var binding: DescriptionAdapterHcBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HentaiCafeDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HentaiCafeDescriptionViewHolder {
@ -48,24 +40,21 @@ class HentaiCafeDescriptionAdapter(
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp) binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
binding.artist.longClicks() binding.artist.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( binding.artist.text.toString(),
binding.artist.text.toString(), binding.artist.text.toString()
binding.artist.text.toString() )
) true
} }
.launchIn(scope)
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -13,13 +13,6 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.HitomiSearchMetadata import exh.metadata.metadata.HitomiSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import java.util.Date import java.util.Date
class HitomiDescriptionAdapter( class HitomiDescriptionAdapter(
@ -27,7 +20,6 @@ class HitomiDescriptionAdapter(
) : ) :
RecyclerView.Adapter<HitomiDescriptionAdapter.HitomiDescriptionViewHolder>() { RecyclerView.Adapter<HitomiDescriptionAdapter.HitomiDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterHiBinding private lateinit var binding: DescriptionAdapterHiBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HitomiDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HitomiDescriptionViewHolder {
@ -63,25 +55,22 @@ class HitomiDescriptionAdapter(
binding.language, binding.language,
binding.whenPosted binding.whenPosted
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -14,13 +14,6 @@ import exh.metadata.MetadataUtil.getRatingString
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import kotlin.math.round import kotlin.math.round
class MangaDexDescriptionAdapter( class MangaDexDescriptionAdapter(
@ -28,7 +21,6 @@ class MangaDexDescriptionAdapter(
) : ) :
RecyclerView.Adapter<MangaDexDescriptionAdapter.MangaDexDescriptionViewHolder>() { RecyclerView.Adapter<MangaDexDescriptionAdapter.MangaDexDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterMdBinding private lateinit var binding: DescriptionAdapterMdBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaDexDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MangaDexDescriptionViewHolder {
@ -55,24 +47,21 @@ class MangaDexDescriptionAdapter(
binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp) binding.moreInfo.bindDrawable(itemView.context, R.drawable.ic_info_24dp)
binding.rating.longClicks() binding.rating.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( binding.rating.text.toString(),
binding.rating.text.toString(), binding.rating.text.toString()
binding.rating.text.toString() )
) true
} }
.launchIn(scope)
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -14,13 +14,6 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.NHentaiSearchMetadata import exh.metadata.metadata.NHentaiSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import java.util.Date import java.util.Date
class NHentaiDescriptionAdapter( class NHentaiDescriptionAdapter(
@ -28,7 +21,6 @@ class NHentaiDescriptionAdapter(
) : ) :
RecyclerView.Adapter<NHentaiDescriptionAdapter.NHentaiDescriptionViewHolder>() { RecyclerView.Adapter<NHentaiDescriptionAdapter.NHentaiDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterNhBinding private lateinit var binding: DescriptionAdapterNhBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NHentaiDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NHentaiDescriptionViewHolder {
@ -80,25 +72,22 @@ class NHentaiDescriptionAdapter(
binding.pages, binding.pages,
binding.whenPosted binding.whenPosted
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -14,13 +14,6 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.PervEdenSearchMetadata import exh.metadata.metadata.PervEdenSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import java.util.Locale import java.util.Locale
import kotlin.math.round import kotlin.math.round
@ -29,7 +22,6 @@ class PervEdenDescriptionAdapter(
) : ) :
RecyclerView.Adapter<PervEdenDescriptionAdapter.PervEdenDescriptionViewHolder>() { RecyclerView.Adapter<PervEdenDescriptionAdapter.PervEdenDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterPeBinding private lateinit var binding: DescriptionAdapterPeBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PervEdenDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PervEdenDescriptionViewHolder {
@ -70,25 +62,22 @@ class PervEdenDescriptionAdapter(
binding.language, binding.language,
binding.rating binding.rating
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -14,13 +14,6 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.PururinSearchMetadata import exh.metadata.metadata.PururinSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import kotlin.math.round import kotlin.math.round
class PururinDescriptionAdapter( class PururinDescriptionAdapter(
@ -28,7 +21,6 @@ class PururinDescriptionAdapter(
) : ) :
RecyclerView.Adapter<PururinDescriptionAdapter.PururinDescriptionViewHolder>() { RecyclerView.Adapter<PururinDescriptionAdapter.PururinDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterPuBinding private lateinit var binding: DescriptionAdapterPuBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PururinDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PururinDescriptionViewHolder {
@ -76,25 +68,22 @@ class PururinDescriptionAdapter(
binding.size, binding.size,
binding.uploader binding.uploader
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -14,13 +14,6 @@ import exh.metadata.MetadataUtil
import exh.metadata.bindDrawable import exh.metadata.bindDrawable
import exh.metadata.metadata.TsuminoSearchMetadata import exh.metadata.metadata.TsuminoSearchMetadata
import exh.ui.metadata.MetadataViewController import exh.ui.metadata.MetadataViewController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.android.view.longClicks
import java.util.Date import java.util.Date
import kotlin.math.round import kotlin.math.round
@ -29,7 +22,6 @@ class TsuminoDescriptionAdapter(
) : ) :
RecyclerView.Adapter<TsuminoDescriptionAdapter.TsuminoDescriptionViewHolder>() { RecyclerView.Adapter<TsuminoDescriptionAdapter.TsuminoDescriptionViewHolder>() {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private lateinit var binding: DescriptionAdapterTsBinding private lateinit var binding: DescriptionAdapterTsBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TsuminoDescriptionViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TsuminoDescriptionViewHolder {
@ -77,25 +69,22 @@ class TsuminoDescriptionAdapter(
binding.uploader, binding.uploader,
binding.whenPosted binding.whenPosted
).forEach { textView -> ).forEach { textView ->
textView.longClicks() textView.setOnLongClickListener {
.onEach { itemView.context.copyToClipboard(
itemView.context.copyToClipboard( textView.text.toString(),
textView.text.toString(), textView.text.toString()
textView.text.toString() )
) true
} }
.launchIn(scope)
} }
binding.moreInfo.clicks() binding.moreInfo.setOnClickListener {
.onEach { controller.router?.pushController(
controller.router?.pushController( MetadataViewController(
MetadataViewController( controller.manga
controller.manga ).withFadeTransaction()
).withFadeTransaction() )
) }
}
.launchIn(scope)
} }
} }
} }

View File

@ -134,6 +134,11 @@ class MangadexLoginDialog(bundle: Bundle? = null) : DialogController(bundle) {
} }
} }
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
interface Listener { interface Listener {
fun siteLoginDialogClosed(source: Source) fun siteLoginDialogClosed(source: Source)
} }