Mostly migrate rxbinding to Kotlin Flow version
This commit is contained in:
@@ -16,8 +16,6 @@ import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||
import com.jakewharton.rxbinding.view.clicks
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||
import eu.kanade.tachiyomi.R
|
||||
@@ -36,6 +34,12 @@ import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import timber.log.Timber
|
||||
|
||||
class ChaptersController : NucleusController<ChaptersPresenter>(),
|
||||
@@ -62,6 +66,8 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
|
||||
|
||||
private var lastClickPosition = -1
|
||||
|
||||
private val uiScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
private lateinit var binding: ChaptersControllerBinding
|
||||
|
||||
init {
|
||||
@@ -91,27 +97,32 @@ class ChaptersController : NucleusController<ChaptersPresenter>(),
|
||||
binding.recycler.setHasFixedSize(true)
|
||||
adapter?.fastScroller = binding.fastScroller
|
||||
|
||||
binding.swipeRefresh.refreshes().subscribeUntilDestroy { fetchChaptersFromSource() }
|
||||
binding.swipeRefresh.refreshes()
|
||||
.onEach { fetchChaptersFromSource() }
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.fab.clicks().subscribeUntilDestroy {
|
||||
val item = presenter.getNextUnreadChapter()
|
||||
if (item != null) {
|
||||
// Create animation listener
|
||||
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
openChapter(item.chapter, true)
|
||||
binding.fab.clicks()
|
||||
.onEach {
|
||||
val item = presenter.getNextUnreadChapter()
|
||||
if (item != null) {
|
||||
// Create animation listener
|
||||
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
openChapter(item.chapter, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get coordinates and start animation
|
||||
val coordinates = binding.fab.getCoordinates()
|
||||
if (!binding.revealView.showRevealEffect(coordinates.x, coordinates.y, revealAnimationListener)) {
|
||||
openChapter(item.chapter)
|
||||
// Get coordinates and start animation
|
||||
val coordinates = binding.fab.getCoordinates()
|
||||
if (!binding.revealView.showRevealEffect(coordinates.x, coordinates.y, revealAnimationListener)) {
|
||||
openChapter(item.chapter)
|
||||
}
|
||||
} else {
|
||||
view.context.toast(R.string.no_next_chapter)
|
||||
}
|
||||
} else {
|
||||
view.context.toast(R.string.no_next_chapter)
|
||||
}
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.fab.shrinkOnScroll(binding.recycler)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||
import com.jakewharton.rxbinding.view.clicks
|
||||
import com.jakewharton.rxbinding.view.longClicks
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
@@ -56,6 +53,13 @@ import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.android.view.longClicks
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@@ -70,6 +74,8 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
|
||||
private val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
private val uiScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
private lateinit var binding: MangaInfoControllerBinding
|
||||
|
||||
init {
|
||||
@@ -91,53 +97,79 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
||||
super.onViewCreated(view)
|
||||
|
||||
// Set onclickListener to toggle favorite when favorite button clicked.
|
||||
binding.btnFavorite.clicks().subscribeUntilDestroy { onFavoriteClick() }
|
||||
binding.btnFavorite.clicks()
|
||||
.onEach { onFavoriteClick() }
|
||||
.launchIn(uiScope)
|
||||
|
||||
// Set onLongClickListener to manage categories when favorite button is clicked.
|
||||
binding.btnFavorite.longClicks().subscribeUntilDestroy { onFavoriteLongClick() }
|
||||
binding.btnFavorite.longClicks()
|
||||
.onEach { onFavoriteLongClick() }
|
||||
.launchIn(uiScope)
|
||||
|
||||
if (presenter.source is HttpSource) {
|
||||
binding.btnWebview.visible()
|
||||
binding.btnShare.visible()
|
||||
|
||||
binding.btnWebview.clicks().subscribeUntilDestroy { openInWebView() }
|
||||
binding.btnShare.clicks().subscribeUntilDestroy { shareManga() }
|
||||
binding.btnWebview.clicks()
|
||||
.onEach { openInWebView() }
|
||||
.launchIn(uiScope)
|
||||
binding.btnShare.clicks()
|
||||
.onEach { shareManga() }
|
||||
.launchIn(uiScope)
|
||||
}
|
||||
|
||||
// Set SwipeRefresh to refresh manga data.
|
||||
binding.swipeRefresh.refreshes().subscribeUntilDestroy { fetchMangaFromSource() }
|
||||
binding.swipeRefresh.refreshes()
|
||||
.onEach { fetchMangaFromSource() }
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaFullTitle.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(view.context.getString(R.string.title), binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
binding.mangaFullTitle.longClicks()
|
||||
.onEach {
|
||||
copyToClipboard(view.context.getString(R.string.title), binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaFullTitle.clicks().subscribeUntilDestroy {
|
||||
performGlobalSearch(binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
binding.mangaFullTitle.clicks()
|
||||
.onEach {
|
||||
performGlobalSearch(binding.mangaFullTitle.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaArtist.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(binding.mangaArtistLabel.text.toString(), binding.mangaArtist.text.toString())
|
||||
}
|
||||
binding.mangaArtist.longClicks()
|
||||
.onEach {
|
||||
copyToClipboard(binding.mangaArtistLabel.text.toString(), binding.mangaArtist.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaArtist.clicks().subscribeUntilDestroy {
|
||||
performGlobalSearch(binding.mangaArtist.text.toString())
|
||||
}
|
||||
binding.mangaArtist.clicks()
|
||||
.onEach {
|
||||
performGlobalSearch(binding.mangaArtist.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaAuthor.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(binding.mangaAuthor.text.toString(), binding.mangaAuthor.text.toString())
|
||||
}
|
||||
binding.mangaAuthor.longClicks()
|
||||
.onEach {
|
||||
copyToClipboard(binding.mangaAuthor.text.toString(), binding.mangaAuthor.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaAuthor.clicks().subscribeUntilDestroy {
|
||||
performGlobalSearch(binding.mangaAuthor.text.toString())
|
||||
}
|
||||
binding.mangaAuthor.clicks()
|
||||
.onEach {
|
||||
performGlobalSearch(binding.mangaAuthor.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaSummary.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(view.context.getString(R.string.description), binding.mangaSummary.text.toString())
|
||||
}
|
||||
binding.mangaSummary.longClicks()
|
||||
.onEach {
|
||||
copyToClipboard(view.context.getString(R.string.description), binding.mangaSummary.text.toString())
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
binding.mangaCover.longClicks().subscribeUntilDestroy {
|
||||
copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
||||
}
|
||||
binding.mangaCover.longClicks()
|
||||
.onEach {
|
||||
copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
|
||||
@@ -6,13 +6,17 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import timber.log.Timber
|
||||
|
||||
class TrackController : NucleusController<TrackPresenter>(),
|
||||
@@ -23,6 +27,8 @@ class TrackController : NucleusController<TrackPresenter>(),
|
||||
|
||||
private var adapter: TrackAdapter? = null
|
||||
|
||||
private val uiScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
private lateinit var binding: TrackControllerBinding
|
||||
|
||||
init {
|
||||
@@ -47,7 +53,9 @@ class TrackController : NucleusController<TrackPresenter>(),
|
||||
binding.trackRecycler.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.trackRecycler.adapter = adapter
|
||||
binding.swipeRefresh.isEnabled = false
|
||||
binding.swipeRefresh.refreshes().subscribeUntilDestroy { presenter.refresh() }
|
||||
binding.swipeRefresh.refreshes()
|
||||
.onEach { presenter.refresh() }
|
||||
.launchIn(uiScope)
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
|
||||
@@ -4,24 +4,27 @@ import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.jakewharton.rxbinding.widget.itemClicks
|
||||
import com.jakewharton.rxbinding.widget.textChanges
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.util.lang.plusAssign
|
||||
import eu.kanade.tachiyomi.util.view.invisible
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.progress
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search
|
||||
import kotlinx.android.synthetic.main.track_search_dialog.view.track_search_list
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.subscriptions.CompositeSubscription
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.widget.itemClicks
|
||||
import reactivecircus.flowbinding.android.widget.textChanges
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@@ -35,13 +38,11 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
private val service: TrackService
|
||||
|
||||
private var subscriptions = CompositeSubscription()
|
||||
|
||||
private var searchTextSubscription: Subscription? = null
|
||||
|
||||
private val trackController
|
||||
get() = targetController as TrackController
|
||||
|
||||
private val uiScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
constructor(target: TrackController, service: TrackService) : super(Bundle().apply {
|
||||
putInt(KEY_SERVICE, service.id)
|
||||
}) {
|
||||
@@ -64,10 +65,6 @@ class TrackSearchDialog : DialogController {
|
||||
.onNeutral { _, _ -> onRemoveButtonClick() }
|
||||
.build()
|
||||
|
||||
if (subscriptions.isUnsubscribed) {
|
||||
subscriptions = CompositeSubscription()
|
||||
}
|
||||
|
||||
dialogView = dialog.view
|
||||
onViewCreated(dialog.view, savedViewState)
|
||||
|
||||
@@ -83,9 +80,11 @@ class TrackSearchDialog : DialogController {
|
||||
// Set listeners
|
||||
selectedItem = null
|
||||
|
||||
subscriptions += view.track_search_list.itemClicks().subscribe { position ->
|
||||
selectedItem = adapter.getItem(position)
|
||||
}
|
||||
view.track_search_list.itemClicks()
|
||||
.onEach { position ->
|
||||
selectedItem = adapter.getItem(position)
|
||||
}
|
||||
.launchIn(uiScope)
|
||||
|
||||
// Do an initial search based on the manga's title
|
||||
if (savedState == null) {
|
||||
@@ -97,24 +96,18 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
subscriptions.unsubscribe()
|
||||
dialogView = null
|
||||
adapter = null
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
searchTextSubscription = dialogView!!.track_search.textChanges()
|
||||
.skip(1)
|
||||
.debounce(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
|
||||
dialogView!!.track_search.textChanges(false)
|
||||
.debounce(TimeUnit.SECONDS.toMillis(1))
|
||||
.map { it.toString() }
|
||||
.filter(String::isNotBlank)
|
||||
.subscribe { search(it) }
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
super.onDetach(view)
|
||||
searchTextSubscription?.unsubscribe()
|
||||
.filter { it.isNotBlank() }
|
||||
.onEach { search(it) }
|
||||
.launchIn(uiScope)
|
||||
}
|
||||
|
||||
private fun search(query: String) {
|
||||
|
||||
Reference in New Issue
Block a user