Show related manga
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package org.koitharu.kotatsu.details.domain
|
||||
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import javax.inject.Inject
|
||||
|
||||
class RelatedMangaUseCase @Inject constructor(
|
||||
private val mangaRepositoryFactory: MangaRepository.Factory,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(seed: Manga) = runCatchingCancellable {
|
||||
mangaRepositoryFactory.create(seed.source).getRelated(seed)
|
||||
}.onFailure {
|
||||
it.printStackTraceDebug()
|
||||
}.getOrNull()
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter
|
||||
import org.koitharu.kotatsu.core.model.countChaptersByBranch
|
||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration
|
||||
@@ -45,6 +46,9 @@ import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.image.ui.ImageActivity
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.ui.adapter.mangaGridItemAD
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.size.StaticItemSizeResolver
|
||||
import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
@@ -87,6 +91,9 @@ class DetailsFragment :
|
||||
binding.infoLayout.textViewSource.setOnClickListener(this)
|
||||
binding.textViewDescription.movementMethod = LinkMovementMethod.getInstance()
|
||||
binding.chipsTags.onChipClickListener = this
|
||||
binding.recyclerViewRelated.addItemDecoration(
|
||||
SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)),
|
||||
)
|
||||
TitleScrollCoordinator(binding.textViewTitle).attach(binding.scrollView)
|
||||
viewModel.manga.filterNotNull().observe(viewLifecycleOwner, ::onMangaUpdated)
|
||||
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
||||
@@ -96,6 +103,7 @@ class DetailsFragment :
|
||||
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
|
||||
viewModel.chapters.observe(viewLifecycleOwner, ::onChaptersChanged)
|
||||
viewModel.localSize.observe(viewLifecycleOwner, ::onLocalSizeChanged)
|
||||
viewModel.relatedManga.observe(viewLifecycleOwner, ::onRelatedMangaChanged)
|
||||
}
|
||||
|
||||
override fun onItemClick(item: Bookmark, view: View) {
|
||||
@@ -193,6 +201,24 @@ class DetailsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRelatedMangaChanged(related: List<MangaItemModel>) {
|
||||
if (related.isEmpty()) {
|
||||
requireViewBinding().groupRelated.isVisible = false
|
||||
return
|
||||
}
|
||||
val rv = viewBinding?.recyclerViewRelated ?: return
|
||||
val adapter = (rv.adapter as? BaseListAdapter) ?: BaseListAdapter(
|
||||
mangaGridItemAD(
|
||||
coil, viewLifecycleOwner,
|
||||
StaticItemSizeResolver(resources.getDimensionPixelSize(R.dimen.smaller_grid_width)),
|
||||
) { item, view ->
|
||||
startActivity(DetailsActivity.newIntent(view.context, item), scaleUpActivityOptionsOf(view))
|
||||
},
|
||||
).also { rv.adapter = it }
|
||||
adapter.items = related
|
||||
requireViewBinding().groupRelated.isVisible = true
|
||||
}
|
||||
|
||||
private fun onHistoryChanged(history: HistoryInfo) {
|
||||
requireViewBinding().progressView.setPercent(history.history?.percent ?: PROGRESS_NONE, animate = true)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
@@ -34,6 +35,7 @@ import org.koitharu.kotatsu.core.model.getPreferredBranch
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
@@ -46,12 +48,16 @@ import org.koitharu.kotatsu.core.util.ext.toFileOrNull
|
||||
import org.koitharu.kotatsu.details.domain.BranchComparator
|
||||
import org.koitharu.kotatsu.details.domain.DetailsInteractor
|
||||
import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase
|
||||
import org.koitharu.kotatsu.details.domain.RelatedMangaUseCase
|
||||
import org.koitharu.kotatsu.details.domain.model.DoubleManga
|
||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||
import org.koitharu.kotatsu.details.ui.model.HistoryInfo
|
||||
import org.koitharu.kotatsu.details.ui.model.MangaBranch
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageChanges
|
||||
import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase
|
||||
import org.koitharu.kotatsu.local.domain.model.LocalManga
|
||||
@@ -74,6 +80,8 @@ class DetailsViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase,
|
||||
private val doubleMangaLoadUseCase: DoubleMangaLoadUseCase,
|
||||
private val relatedMangaUseCase: RelatedMangaUseCase,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
networkState: NetworkState,
|
||||
) : BaseViewModel() {
|
||||
|
||||
@@ -155,6 +163,18 @@ class DetailsViewModel @Inject constructor(
|
||||
val scrobblingInfo: StateFlow<List<ScrobblingInfo>> = interactor.observeScrobblingInfo(mangaId)
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
val relatedManga: StateFlow<List<MangaItemModel>> = doubleManga.map {
|
||||
it?.remote
|
||||
}.distinctUntilChangedBy { it?.id }
|
||||
.mapLatest {
|
||||
if (it != null) {
|
||||
relatedMangaUseCase.invoke(it)?.toUi(ListMode.GRID, extraProvider).orEmpty()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
|
||||
|
||||
val branches: StateFlow<List<MangaBranch>> = combine(
|
||||
doubleManga,
|
||||
selectedBranch,
|
||||
|
||||
Reference in New Issue
Block a user