Linting fixes

This commit is contained in:
arkon
2020-04-25 14:24:45 -04:00
parent 4da760d614
commit 3f63b320c4
272 changed files with 4167 additions and 3602 deletions
@@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.android.synthetic.main.source_main_controller_card.title
class LangHolder(view: View, adapter: FlexibleAdapter<*>) :
BaseFlexibleViewHolder(view, adapter) {
BaseFlexibleViewHolder(view, adapter) {
fun bind(item: LangItem) {
title.text = LocaleHelper.getSourceDisplayName(item.code, itemView.context)
@@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
* @param controller instance of [SourceController].
*/
class SourceAdapter(val controller: SourceController) :
FlexibleAdapter<IFlexible<*>>(null, controller, true) {
FlexibleAdapter<IFlexible<*>>(null, controller, true) {
val cardBackground = controller.activity!!.getResourceColor(R.attr.colorSurface)
@@ -28,7 +28,7 @@ import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController
import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
import eu.kanade.tachiyomi.ui.source.latest.LatestUpdatesController
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
@@ -44,12 +44,13 @@ import uy.kohesive.injekt.api.get
* [SourceAdapter.OnBrowseClickListener] call function data on browse item click.
* [SourceAdapter.OnLatestClickListener] call function data on latest item click
*/
class SourceController : NucleusController<SourceMainControllerBinding, SourcePresenter>(),
RootController,
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener,
SourceAdapter.OnBrowseClickListener,
SourceAdapter.OnLatestClickListener {
class SourceController :
NucleusController<SourceMainControllerBinding, SourcePresenter>(),
RootController,
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener,
SourceAdapter.OnBrowseClickListener,
SourceAdapter.OnLatestClickListener {
private val preferences: PreferencesHelper = Injekt.get()
@@ -122,21 +123,21 @@ class SourceController : NucleusController<SourceMainControllerBinding, SourcePr
val isPinned = item.header?.code?.equals(SourcePresenter.PINNED_KEY) ?: false
MaterialDialog(activity)
.title(text = item.source.name)
.listItems(
items = listOf(
activity.getString(R.string.action_hide),
activity.getString(if (isPinned) R.string.action_unpin else R.string.action_pin)
),
waitForPositiveButton = false
) { dialog, which, _ ->
when (which) {
0 -> hideCatalogue(item.source)
1 -> pinCatalogue(item.source, isPinned)
}
dialog.dismiss()
.title(text = item.source.name)
.listItems(
items = listOf(
activity.getString(R.string.action_hide),
activity.getString(if (isPinned) R.string.action_unpin else R.string.action_pin)
),
waitForPositiveButton = false
) { dialog, which, _ ->
when (which) {
0 -> hideCatalogue(item.source)
1 -> pinCatalogue(item.source, isPinned)
}
.show()
dialog.dismiss()
}
.show()
}
private fun hideCatalogue(source: Source) {
@@ -218,9 +219,11 @@ class SourceController : NucleusController<SourceMainControllerBinding, SourcePr
when (item.itemId) {
// Initialize option to open catalogue settings.
R.id.action_settings -> {
router.pushController((RouterTransaction.with(SettingsSourcesController()))
router.pushController(
(RouterTransaction.with(SettingsSourcesController()))
.popChangeHandler(SettingsSourcesFadeChangeHandler())
.pushChangeHandler(FadeChangeHandler()))
.pushChangeHandler(FadeChangeHandler())
)
}
}
return super.onOptionsItemSelected(item)
@@ -23,7 +23,8 @@ class SourceDividerItemDecoration(context: Context) : RecyclerView.ItemDecoratio
val child = parent.getChildAt(i)
val holder = parent.getChildViewHolder(child)
if (holder is SourceHolder &&
parent.getChildViewHolder(parent.getChildAt(i + 1)) is SourceHolder) {
parent.getChildViewHolder(parent.getChildAt(i + 1)) is SourceHolder
) {
val params = child.layoutParams as RecyclerView.LayoutParams
val top = child.bottom + params.bottomMargin
val bottom = top + divider.intrinsicHeight
@@ -16,8 +16,8 @@ import kotlinx.android.synthetic.main.source_main_controller_card_item.source_la
import kotlinx.android.synthetic.main.source_main_controller_card_item.title
class SourceHolder(view: View, override val adapter: SourceAdapter) :
BaseFlexibleViewHolder(view, adapter),
SlicedHolder {
BaseFlexibleViewHolder(view, adapter),
SlicedHolder {
override val slice = Slice(card).apply {
setColor(adapter.cardBackground)
@@ -15,7 +15,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
* @param header The header for this item.
*/
data class SourceItem(val source: CatalogueSource, val header: LangItem? = null) :
AbstractSectionableItem<SourceHolder, LangItem>(header) {
AbstractSectionableItem<SourceHolder, LangItem>(header) {
/**
* Returns the layout resource of this item.
@@ -75,7 +75,7 @@ class SourcePresenter(
}
sourceSubscription = Observable.just(sourceItems)
.subscribeLatestCache(SourceController::setSources)
.subscribeLatestCache(SourceController::setSources)
}
private fun loadLastUsedSource() {
@@ -83,11 +83,12 @@ class SourcePresenter(
// Emit the first item immediately but delay subsequent emissions by 500ms.
Observable.merge(
sharedObs.take(1),
sharedObs.skip(1).delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()))
.distinctUntilChanged()
.map { item -> (sourceManager.get(item) as? CatalogueSource)?.let { SourceItem(it) } }
.subscribeLatestCache(SourceController::setLastUsedSource)
sharedObs.take(1),
sharedObs.skip(1).delay(500, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
)
.distinctUntilChanged()
.map { item -> (sourceManager.get(item) as? CatalogueSource)?.let { SourceItem(it) } }
.subscribeLatestCache(SourceController::setLastUsedSource)
}
fun updateSources() {
@@ -105,10 +106,10 @@ class SourcePresenter(
val hiddenCatalogues = preferences.hiddenCatalogues().get()
return sourceManager.getCatalogueSources()
.filter { it.lang in languages }
.filterNot { it.id.toString() in hiddenCatalogues }
.sortedBy { "(${it.lang}) ${it.name}" } +
sourceManager.get(LocalSource.ID) as LocalSource
.filter { it.lang in languages }
.filterNot { it.id.toString() in hiddenCatalogues }
.sortedBy { "(${it.lang}) ${it.name}" } +
sourceManager.get(LocalSource.ID) as LocalSource
}
companion object {
@@ -56,15 +56,17 @@ import uy.kohesive.injekt.injectLazy
* Controller to manage the catalogues available in the app.
*/
open class BrowseSourceController(bundle: Bundle) :
NucleusController<SourceControllerBinding, BrowseSourcePresenter>(bundle),
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.EndlessScrollListener,
ChangeMangaCategoriesDialog.Listener {
NucleusController<SourceControllerBinding, BrowseSourcePresenter>(bundle),
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.EndlessScrollListener,
ChangeMangaCategoriesDialog.Listener {
constructor(source: CatalogueSource) : this(Bundle().apply {
putLong(SOURCE_ID_KEY, source.id)
})
constructor(source: CatalogueSource) : this(
Bundle().apply {
putLong(SOURCE_ID_KEY, source.id)
}
)
private val preferences: PreferencesHelper by injectLazy()
@@ -185,10 +187,10 @@ open class BrowseSourceController(bundle: Bundle) :
} else {
(binding.catalogueView.inflate(R.layout.source_recycler_autofit) as AutofitRecyclerView).apply {
numColumnsSubscription = getColumnsPreferenceForCurrentOrientation().asObservable()
.doOnNext { spanCount = it }
.skip(1)
// Set again the adapter to recalculate the covers height
.subscribe { adapter = this@BrowseSourceController.adapter }
.doOnNext { spanCount = it }
.skip(1)
// Set again the adapter to recalculate the covers height
.subscribe { adapter = this@BrowseSourceController.adapter }
(layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
@@ -246,19 +248,20 @@ open class BrowseSourceController(bundle: Bundle) :
.launchIn(scope)
searchItem.fixExpand(
onExpand = { invalidateMenuOnExpand() },
onCollapse = {
searchWithQuery("")
true
}
onExpand = { invalidateMenuOnExpand() },
onCollapse = {
searchWithQuery("")
true
}
)
// Show next display mode
menu.findItem(R.id.action_display_mode).apply {
val icon = if (presenter.isListMode)
val icon = if (presenter.isListMode) {
R.drawable.ic_view_module_24dp
else
} else {
R.drawable.ic_view_list_24dp
}
setIcon(icon)
}
}
@@ -302,8 +305,9 @@ open class BrowseSourceController(bundle: Bundle) :
*/
fun searchWithQuery(newQuery: String) {
// If text didn't change, do nothing
if (presenter.query == newQuery)
if (presenter.query == newQuery) {
return
}
showProgressBar()
adapter?.clear()
@@ -342,7 +346,6 @@ open class BrowseSourceController(bundle: Bundle) :
val message = getErrorMessage(error)
val retryAction = View.OnClickListener {
// If not the first page, show bottom progress bar.
if (adapter.mainItemCount > 0 && progressItem != null) {
adapter.addScrollableFooterWithDelay(progressItem!!, 0, true)
@@ -444,10 +447,11 @@ open class BrowseSourceController(bundle: Bundle) :
* @return the preference.
*/
fun getColumnsPreferenceForCurrentOrientation(): Preference<Int> {
return if (resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT)
return if (resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
preferences.portraitColumns()
else
} else {
preferences.landscapeColumns()
}
}
/**
@@ -514,19 +518,19 @@ open class BrowseSourceController(bundle: Bundle) :
if (manga.favorite) {
MaterialDialog(activity)
.listItems(
items = listOf(activity.getString(R.string.remove_from_library)),
waitForPositiveButton = false
) { _, which, _ ->
when (which) {
0 -> {
presenter.changeMangaFavorite(manga)
adapter?.notifyItemChanged(position)
activity.toast(activity.getString(R.string.manga_removed_library))
}
.listItems(
items = listOf(activity.getString(R.string.remove_from_library)),
waitForPositiveButton = false
) { _, which, _ ->
when (which) {
0 -> {
presenter.changeMangaFavorite(manga)
adapter?.notifyItemChanged(position)
activity.toast(activity.getString(R.string.manga_removed_library))
}
}
.show()
}
.show()
} else {
val categories = presenter.getCategories()
val defaultCategoryId = preferences.defaultCategory()
@@ -559,7 +563,7 @@ open class BrowseSourceController(bundle: Bundle) :
}.toTypedArray()
ChangeMangaCategoriesDialog(this, listOf(manga), categories, preselected)
.showDialog(router)
.showDialog(router)
}
}
}
@@ -115,8 +115,10 @@ open class BrowseSourcePresenter(
query = savedState.getString(::query.name, "")
}
add(prefs.catalogueAsList().asObservable()
.subscribe { setDisplayMode(it) })
add(
prefs.catalogueAsList().asObservable()
.subscribe { setDisplayMode(it) }
)
restartPager()
}
@@ -148,16 +150,19 @@ open class BrowseSourcePresenter(
// Prepare the pager.
pagerSubscription?.let { remove(it) }
pagerSubscription = pager.results()
.observeOn(Schedulers.io())
.map { pair -> pair.first to pair.second.map { networkToLocalManga(it, sourceId) } }
.doOnNext { initializeMangas(it.second) }
.map { pair -> pair.first to pair.second.map { SourceItem(it, catalogueAsList) } }
.observeOn(AndroidSchedulers.mainThread())
.subscribeReplay({ view, (page, mangas) ->
.observeOn(Schedulers.io())
.map { pair -> pair.first to pair.second.map { networkToLocalManga(it, sourceId) } }
.doOnNext { initializeMangas(it.second) }
.map { pair -> pair.first to pair.second.map { SourceItem(it, catalogueAsList) } }
.observeOn(AndroidSchedulers.mainThread())
.subscribeReplay(
{ view, (page, mangas) ->
view.onAddPage(page, mangas)
}, { _, error ->
},
{ _, error ->
Timber.e(error)
})
}
)
// Request first page.
requestNext()
@@ -171,9 +176,12 @@ open class BrowseSourcePresenter(
pageSubscription?.let { remove(it) }
pageSubscription = Observable.defer { pager.requestNext() }
.subscribeFirst({ _, _ ->
.subscribeFirst(
{ _, _ ->
// Nothing to do when onNext is emitted.
}, BrowseSourceController::onAddPageError)
},
BrowseSourceController::onAddPageError
)
}
/**
@@ -199,18 +207,21 @@ open class BrowseSourcePresenter(
private fun subscribeToMangaInitializer() {
initializerSubscription?.let { remove(it) }
initializerSubscription = mangaDetailSubject.observeOn(Schedulers.io())
.flatMap { Observable.from(it) }
.filter { it.thumbnail_url == null && !it.initialized }
.concatMap { getMangaDetailsObservable(it) }
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ manga ->
.flatMap { Observable.from(it) }
.filter { it.thumbnail_url == null && !it.initialized }
.concatMap { getMangaDetailsObservable(it) }
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ manga ->
@Suppress("DEPRECATION")
view?.onMangaInitialized(manga)
}, { error ->
},
{ error ->
Timber.e(error)
})
.apply { add(this) }
}
)
.apply { add(this) }
}
/**
@@ -249,13 +260,13 @@ open class BrowseSourcePresenter(
*/
private fun getMangaDetailsObservable(manga: Manga): Observable<Manga> {
return source.fetchMangaDetails(manga)
.flatMap { networkManga ->
manga.copyFrom(networkManga)
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
Observable.just(manga)
}
.onErrorResumeNext { Observable.just(manga) }
.flatMap { networkManga ->
manga.copyFrom(networkManga)
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
Observable.just(manga)
}
.onErrorResumeNext { Observable.just(manga) }
}
/**
@@ -20,7 +20,7 @@ import kotlinx.android.synthetic.main.source_grid_item.title
* @constructor creates a new catalogue holder.
*/
class SourceGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) :
SourceHolder(view, adapter) {
SourceHolder(view, adapter) {
/**
* Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this
@@ -42,11 +42,11 @@ class SourceGridHolder(private val view: View, private val adapter: FlexibleAdap
GlideApp.with(view.context).clear(thumbnail)
if (!manga.thumbnail_url.isNullOrEmpty()) {
GlideApp.with(view.context)
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.placeholder(android.R.color.transparent)
.into(StateImageViewTarget(thumbnail, progress))
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.placeholder(android.R.color.transparent)
.into(StateImageViewTarget(thumbnail, progress))
}
}
}
@@ -12,7 +12,7 @@ import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
* @param adapter the adapter handling this holder.
*/
abstract class SourceHolder(view: View, adapter: FlexibleAdapter<*>) :
BaseFlexibleViewHolder(view, adapter) {
BaseFlexibleViewHolder(view, adapter) {
/**
* Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this
@@ -17,13 +17,14 @@ import kotlinx.android.synthetic.main.source_grid_item.view.card
import kotlinx.android.synthetic.main.source_grid_item.view.gradient
class SourceItem(val manga: Manga, private val catalogueAsList: Preference<Boolean>) :
AbstractFlexibleItem<SourceHolder>() {
AbstractFlexibleItem<SourceHolder>() {
override fun getLayoutRes(): Int {
return if (catalogueAsList.getOrDefault())
return if (catalogueAsList.getOrDefault()) {
R.layout.source_list_item
else
} else {
R.layout.source_grid_item
}
}
override fun createViewHolder(
@@ -34,9 +35,11 @@ class SourceItem(val manga: Manga, private val catalogueAsList: Preference<Boole
return if (parent is AutofitRecyclerView) {
view.apply {
card.layoutParams = FrameLayout.LayoutParams(
MATCH_PARENT, parent.itemWidth / 3 * 4)
MATCH_PARENT, parent.itemWidth / 3 * 4
)
gradient.layoutParams = FrameLayout.LayoutParams(
MATCH_PARENT, parent.itemWidth / 3 * 4 / 2, Gravity.BOTTOM)
MATCH_PARENT, parent.itemWidth / 3 * 4 / 2, Gravity.BOTTOM
)
}
SourceGridHolder(view, adapter)
} else {
@@ -21,7 +21,7 @@ import kotlinx.android.synthetic.main.source_list_item.title
* @constructor creates a new catalogue holder.
*/
class SourceListHolder(private val view: View, adapter: FlexibleAdapter<*>) :
SourceHolder(view, adapter) {
SourceHolder(view, adapter) {
private val favoriteColor = ContextCompat.getColor(view.context, R.color.material_on_surface_disabled)
private val unfavoriteColor = view.context.getResourceColor(R.attr.colorOnSurface)
@@ -43,13 +43,13 @@ class SourceListHolder(private val view: View, adapter: FlexibleAdapter<*>) :
GlideApp.with(view.context).clear(thumbnail)
if (!manga.thumbnail_url.isNullOrEmpty()) {
GlideApp.with(view.context)
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.circleCrop()
.dontAnimate()
.placeholder(android.R.color.transparent)
.into(thumbnail)
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.circleCrop()
.dontAnimate()
.placeholder(android.R.color.transparent)
.into(thumbnail)
}
}
}
@@ -12,20 +12,21 @@ open class SourcePager(val source: CatalogueSource, val query: String, val filte
override fun requestNext(): Observable<MangasPage> {
val page = currentPage
val observable = if (query.isBlank() && filters.isEmpty())
val observable = if (query.isBlank() && filters.isEmpty()) {
source.fetchPopularManga(page)
else
} else {
source.fetchSearchManga(page, query, filters)
}
return observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
if (it.mangas.isNotEmpty()) {
onPageReceived(it)
} else {
throw NoResultsException()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
if (it.mangas.isNotEmpty()) {
onPageReceived(it)
} else {
throw NoResultsException()
}
}
}
}
@@ -34,10 +34,13 @@ class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<Grou
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.title.text = filter.name
holder.icon.setVectorCompat(if (isExpanded)
R.drawable.ic_expand_more_white_24dp
else
R.drawable.ic_chevron_right_white_24dp)
holder.icon.setVectorCompat(
if (isExpanded) {
R.drawable.ic_expand_more_white_24dp
} else {
R.drawable.ic_chevron_right_white_24dp
}
)
holder.itemView.setOnClickListener(holder)
}
@@ -28,8 +28,10 @@ open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<Selec
val spinner = holder.spinner
spinner.prompt = filter.name
spinner.adapter = ArrayAdapter<Any>(holder.itemView.context,
android.R.layout.simple_spinner_item, filter.values).apply {
spinner.adapter = ArrayAdapter<Any>(
holder.itemView.context,
android.R.layout.simple_spinner_item, filter.values
).apply {
setDropDownViewResource(R.layout.common_spinner_item)
}
spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos ->
@@ -31,10 +31,13 @@ class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGrou
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.title.text = filter.name
holder.icon.setVectorCompat(if (isExpanded)
R.drawable.ic_expand_more_white_24dp
else
R.drawable.ic_chevron_right_white_24dp)
holder.icon.setVectorCompat(
if (isExpanded) {
R.drawable.ic_expand_more_white_24dp
} else {
R.drawable.ic_chevron_right_white_24dp
}
)
holder.itemView.setOnClickListener(holder)
}
@@ -35,9 +35,11 @@ class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem
val i = filter.values.indexOf(name)
fun getIcon() = when (filter.state) {
Filter.Sort.Selection(i, false) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_arrow_down_white_32dp, null)
Filter.Sort.Selection(i, false) ->
VectorDrawableCompat.create(view.resources, R.drawable.ic_arrow_down_white_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
Filter.Sort.Selection(i, true) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_arrow_up_white_32dp, null)
Filter.Sort.Selection(i, true) ->
VectorDrawableCompat.create(view.resources, R.drawable.ic_arrow_up_white_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
else -> ContextCompat.getDrawable(view.context, R.drawable.empty_drawable_32dp)
}
@@ -33,16 +33,21 @@ open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem<TriS
val view = holder.text
view.text = filter.name
fun getIcon() = VectorDrawableCompat.create(view.resources, when (filter.state) {
Filter.TriState.STATE_IGNORE -> TR.drawable.ic_check_box_outline_blank_24dp
Filter.TriState.STATE_INCLUDE -> TR.drawable.ic_check_box_24dp
Filter.TriState.STATE_EXCLUDE -> TR.drawable.ic_check_box_x_24dp
else -> throw Exception("Unknown state")
}, null)?.apply {
val color = if (filter.state == Filter.TriState.STATE_INCLUDE)
fun getIcon() = VectorDrawableCompat.create(
view.resources,
when (filter.state) {
Filter.TriState.STATE_IGNORE -> TR.drawable.ic_check_box_outline_blank_24dp
Filter.TriState.STATE_INCLUDE -> TR.drawable.ic_check_box_24dp
Filter.TriState.STATE_EXCLUDE -> TR.drawable.ic_check_box_x_24dp
else -> throw Exception("Unknown state")
},
null
)?.apply {
val color = if (filter.state == Filter.TriState.STATE_INCLUDE) {
view.context.getResourceColor(R.attr.colorAccent)
else
} else {
ContextCompat.getColor(view.context, R.color.material_on_background_disabled)
}
setTint(color)
}
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.os.Bundle
import android.os.Parcelable
@@ -12,7 +12,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
* @param controller instance of [GlobalSearchController].
*/
class GlobalSearchAdapter(val controller: GlobalSearchController) :
FlexibleAdapter<GlobalSearchItem>(null, controller, true) {
FlexibleAdapter<GlobalSearchItem>(null, controller, true) {
/**
* Bundle where the view state of the holders is saved.
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.data.database.models.Manga
@@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
* @param controller instance of [GlobalSearchController].
*/
class GlobalSearchCardAdapter(controller: GlobalSearchController) :
FlexibleAdapter<GlobalSearchCardItem>(null, controller, true) {
FlexibleAdapter<GlobalSearchCardItem>(null, controller, true) {
/**
* Listen for browse item clicks.
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.view.View
import com.bumptech.glide.load.engine.DiskCacheStrategy
@@ -43,12 +43,12 @@ class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) :
GlideApp.with(itemView.context).clear(itemImage)
if (!manga.thumbnail_url.isNullOrEmpty()) {
GlideApp.with(itemView.context)
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.skipMemoryCache(true)
.placeholder(android.R.color.transparent)
.into(StateImageViewTarget(itemImage, progress))
.load(manga.toMangaThumbnail())
.diskCacheStrategy(DiskCacheStrategy.DATA)
.centerCrop()
.skipMemoryCache(true)
.placeholder(android.R.color.transparent)
.into(StateImageViewTarget(itemImage, progress))
}
}
}
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.view.View
import androidx.recyclerview.widget.RecyclerView
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.os.Bundle
import android.view.LayoutInflater
@@ -31,7 +31,7 @@ open class GlobalSearchController(
protected val initialQuery: String? = null,
protected val extensionFilter: String? = null
) : NucleusController<GlobalSearchControllerBinding, GlobalSearchPresenter>(),
GlobalSearchCardAdapter.OnMangaClickListener {
GlobalSearchCardAdapter.OnMangaClickListener {
/**
* Adapter containing search results grouped by lang.
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
@@ -18,7 +18,7 @@ import kotlinx.android.synthetic.main.global_search_controller_card.title
* @param adapter instance of [GlobalSearchAdapter]
*/
class GlobalSearchHolder(view: View, val adapter: GlobalSearchAdapter) :
BaseFlexibleViewHolder(view, adapter) {
BaseFlexibleViewHolder(view, adapter) {
/**
* Adapter containing manga from search results.
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.view.View
import androidx.recyclerview.widget.RecyclerView
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.ui.source.global_search
package eu.kanade.tachiyomi.ui.source.globalsearch
import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@@ -73,11 +73,13 @@ open class GlobalSearchPresenter(
super.onCreate(savedState)
extensionFilter = savedState?.getString(GlobalSearchPresenter::extensionFilter.name)
?: initialExtensionFilter
?: initialExtensionFilter
// Perform a search with previous or initial state
search(savedState?.getString(BrowseSourcePresenter::query.name)
?: initialQuery.orEmpty())
search(
savedState?.getString(BrowseSourcePresenter::query.name)
?: initialQuery.orEmpty()
)
}
override fun onDestroy() {
@@ -104,9 +106,9 @@ open class GlobalSearchPresenter(
val pinnedCatalogues = preferences.pinnedCatalogues().get()
return sourceManager.getCatalogueSources()
.filter { it.lang in languages }
.filterNot { it.id.toString() in hiddenCatalogues }
.sortedWith(compareBy({ it.id.toString() !in pinnedCatalogues }, { "(${it.lang}) ${it.name}" }))
.filter { it.lang in languages }
.filterNot { it.id.toString() in hiddenCatalogues }
.sortedWith(compareBy({ it.id.toString() !in pinnedCatalogues }, { "(${it.lang}) ${it.name}" }))
}
private fun getSourcesToQuery(): List<CatalogueSource> {
@@ -117,10 +119,10 @@ open class GlobalSearchPresenter(
}
val filterSources = extensionManager.installedExtensions
.filter { it.pkgName == filter }
.flatMap { it.sources }
.filter { it in enabledSources }
.filterIsInstance<CatalogueSource>()
.filter { it.pkgName == filter }
.flatMap { it.sources }
.filter { it in enabledSources }
.filterIsInstance<CatalogueSource>()
if (filterSources.isEmpty()) {
return enabledSources
@@ -157,29 +159,35 @@ open class GlobalSearchPresenter(
fetchSourcesSubscription?.unsubscribe()
fetchSourcesSubscription = Observable.from(sources)
.flatMap({ source ->
.flatMap(
{ source ->
Observable.defer { source.fetchSearchManga(1, query, FilterList()) }
.subscribeOn(Schedulers.io())
.onErrorReturn { MangasPage(emptyList(), false) } // Ignore timeouts or other exceptions
.map { it.mangas.take(10) } // Get at most 10 manga from search result.
.map { list -> list.map { networkToLocalManga(it, source.id) } } // Convert to local manga.
.doOnNext { fetchImage(it, source) } // Load manga covers.
.map { list -> createCatalogueSearchItem(source, list.map { GlobalSearchCardItem(it) }) }
}, 5)
.observeOn(AndroidSchedulers.mainThread())
// Update matching source with the obtained results
.map { result ->
items.map { item -> if (item.source == result.source) result else item }
}
// Update current state
.doOnNext { items = it }
// Deliver initial state
.startWith(initialItems)
.subscribeLatestCache({ view, manga ->
.subscribeOn(Schedulers.io())
.onErrorReturn { MangasPage(emptyList(), false) } // Ignore timeouts or other exceptions
.map { it.mangas.take(10) } // Get at most 10 manga from search result.
.map { list -> list.map { networkToLocalManga(it, source.id) } } // Convert to local manga.
.doOnNext { fetchImage(it, source) } // Load manga covers.
.map { list -> createCatalogueSearchItem(source, list.map { GlobalSearchCardItem(it) }) }
},
5
)
.observeOn(AndroidSchedulers.mainThread())
// Update matching source with the obtained results
.map { result ->
items.map { item -> if (item.source == result.source) result else item }
}
// Update current state
.doOnNext { items = it }
// Deliver initial state
.startWith(initialItems)
.subscribeLatestCache(
{ view, manga ->
view.setItems(manga)
}, { _, error ->
},
{ _, error ->
Timber.e(error)
})
}
)
}
/**
@@ -197,21 +205,24 @@ open class GlobalSearchPresenter(
private fun initializeFetchImageSubscription() {
fetchImageSubscription?.unsubscribe()
fetchImageSubscription = fetchImageSubject.observeOn(Schedulers.io())
.flatMap { pair ->
val source = pair.second
Observable.from(pair.first).filter { it.thumbnail_url == null && !it.initialized }
.map { Pair(it, source) }
.concatMap { getMangaDetailsObservable(it.first, it.second) }
.map { Pair(source as CatalogueSource, it) }
}
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ (source, manga) ->
.flatMap { pair ->
val source = pair.second
Observable.from(pair.first).filter { it.thumbnail_url == null && !it.initialized }
.map { Pair(it, source) }
.concatMap { getMangaDetailsObservable(it.first, it.second) }
.map { Pair(source as CatalogueSource, it) }
}
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ (source, manga) ->
@Suppress("DEPRECATION")
view?.onMangaInitialized(source, manga)
}, { error ->
},
{ error ->
Timber.e(error)
})
}
)
}
/**
@@ -222,13 +233,13 @@ open class GlobalSearchPresenter(
*/
private fun getMangaDetailsObservable(manga: Manga, source: Source): Observable<Manga> {
return source.fetchMangaDetails(manga)
.flatMap { networkManga ->
manga.copyFrom(networkManga)
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
Observable.just(manga)
}
.onErrorResumeNext { Observable.just(manga) }
.flatMap { networkManga ->
manga.copyFrom(networkManga)
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
Observable.just(manga)
}
.onErrorResumeNext { Observable.just(manga) }
}
/**
@@ -12,9 +12,11 @@ import eu.kanade.tachiyomi.ui.source.browse.BrowseSourcePresenter
*/
class LatestUpdatesController(bundle: Bundle) : BrowseSourceController(bundle) {
constructor(source: CatalogueSource) : this(Bundle().apply {
putLong(SOURCE_ID_KEY, source.id)
})
constructor(source: CatalogueSource) : this(
Bundle().apply {
putLong(SOURCE_ID_KEY, source.id)
}
)
override fun createPresenter(): BrowseSourcePresenter {
return LatestUpdatesPresenter(args.getLong(SOURCE_ID_KEY))
@@ -14,8 +14,8 @@ class LatestUpdatesPager(val source: CatalogueSource) : Pager() {
override fun requestNext(): Observable<MangasPage> {
return source.fetchLatestUpdates(currentPage)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext { onPageReceived(it) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext { onPageReceived(it) }
}
}