Refactor manga list model mapping
This commit is contained in:
@@ -15,11 +15,13 @@ import org.koitharu.kotatsu.core.model.chaptersCount
|
||||
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
@@ -34,7 +36,8 @@ class AlternativesViewModel @Inject constructor(
|
||||
private val mangaRepositoryFactory: MangaRepository.Factory,
|
||||
private val alternativesUseCase: AlternativesUseCase,
|
||||
private val migrateUseCase: MigrateUseCase,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val settings: AppSettings,
|
||||
) : BaseViewModel() {
|
||||
|
||||
val manga = savedStateHandle.require<ParcelableManga>(MangaIntent.KEY_MANGA).manga
|
||||
@@ -53,7 +56,7 @@ class AlternativesViewModel @Inject constructor(
|
||||
.map {
|
||||
MangaAlternativeModel(
|
||||
manga = it,
|
||||
progress = extraProvider.getProgress(it.id),
|
||||
progress = getProgress(it.id),
|
||||
referenceChapters = refCount,
|
||||
)
|
||||
}.runningFold<MangaAlternativeModel, List<ListModel>>(listOf(LoadingState)) { acc, item ->
|
||||
@@ -86,13 +89,11 @@ class AlternativesViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun mapList(list: List<Manga>, refCount: Int): List<MangaAlternativeModel> {
|
||||
return list.map {
|
||||
MangaAlternativeModel(
|
||||
manga = it,
|
||||
progress = extraProvider.getProgress(it.id),
|
||||
referenceChapters = refCount,
|
||||
)
|
||||
private suspend fun getProgress(mangaId: Long): Float {
|
||||
return if (settings.isReadingIndicatorsEnabled) {
|
||||
historyRepository.getProgress(mangaId)
|
||||
} else {
|
||||
PROGRESS_NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,11 +89,11 @@ import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavoriteSheet
|
||||
import org.koitharu.kotatsu.image.ui.ImageActivity
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
|
||||
import org.koitharu.kotatsu.list.ui.adapter.mangaGridItemAD
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.size.StaticItemSizeResolver
|
||||
import org.koitharu.kotatsu.local.ui.info.LocalInfoDialog
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
@@ -122,7 +122,7 @@ class DetailsActivity :
|
||||
lateinit var coil: ImageLoader
|
||||
|
||||
@Inject
|
||||
lateinit var tagHighlighter: ListExtraProvider
|
||||
lateinit var listMapper: MangaListMapper
|
||||
|
||||
private val viewModel: DetailsViewModel by viewModels()
|
||||
private lateinit var menuProvider: DetailsMenuProvider
|
||||
@@ -391,7 +391,7 @@ class DetailsActivity :
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRelatedMangaChanged(related: List<MangaItemModel>) {
|
||||
private fun onRelatedMangaChanged(related: List<MangaListModel>) {
|
||||
if (related.isEmpty()) {
|
||||
viewBinding.groupRelated.isVisible = false
|
||||
return
|
||||
@@ -613,15 +613,7 @@ class DetailsActivity :
|
||||
|
||||
private fun bindTags(manga: Manga) {
|
||||
viewBinding.chipsTags.isVisible = manga.tags.isNotEmpty()
|
||||
viewBinding.chipsTags.setChips(
|
||||
manga.tags.map { tag ->
|
||||
ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
tint = tagHighlighter.getTagTint(tag),
|
||||
data = tag,
|
||||
)
|
||||
},
|
||||
)
|
||||
viewBinding.chipsTags.setChips(listMapper.mapTags(manga.tags))
|
||||
}
|
||||
|
||||
private fun loadCover(manga: Manga) {
|
||||
|
||||
@@ -50,9 +50,8 @@ 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.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageChanges
|
||||
import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase
|
||||
import org.koitharu.kotatsu.local.domain.model.LocalManga
|
||||
@@ -76,7 +75,7 @@ class DetailsViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase,
|
||||
private val relatedMangaUseCase: RelatedMangaUseCase,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
private val detailsLoadUseCase: DetailsLoadUseCase,
|
||||
private val progressUpdateUseCase: ProgressUpdateUseCase,
|
||||
private val readingTimeUseCase: ReadingTimeUseCase,
|
||||
@@ -171,9 +170,12 @@ class DetailsViewModel @Inject constructor(
|
||||
val scrobblingInfo: StateFlow<List<ScrobblingInfo>> = interactor.observeScrobblingInfo(mangaId)
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
val relatedManga: StateFlow<List<MangaItemModel>> = manga.mapLatest {
|
||||
val relatedManga: StateFlow<List<MangaListModel>> = manga.mapLatest {
|
||||
if (it != null && settings.isRelatedMangaEnabled) {
|
||||
relatedMangaUseCase.invoke(it)?.toUi(ListMode.GRID, extraProvider).orEmpty()
|
||||
mangaListMapper.toListModelList(
|
||||
manga = relatedMangaUseCase(it).orEmpty(),
|
||||
mode = ListMode.GRID,
|
||||
)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@ import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -34,7 +33,7 @@ class RelatedListViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
mangaRepositoryFactory: MangaRepository.Factory,
|
||||
settings: AppSettings,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
) : MangaListViewModel(settings, downloadScheduler) {
|
||||
|
||||
@@ -53,7 +52,7 @@ class RelatedListViewModel @Inject constructor(
|
||||
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
|
||||
list == null -> listOf(LoadingState)
|
||||
list.isEmpty() -> listOf(createEmptyState())
|
||||
else -> list.toUi(mode, extraProvider)
|
||||
else -> mangaListMapper.toListModelList(list, mode)
|
||||
}
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.koitharu.kotatsu.list.ui.model.EmptyHint
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaCompactListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
@@ -190,7 +190,7 @@ class ExploreViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun List<Manga>.toRecommendationList() = map { manga ->
|
||||
MangaListModel(
|
||||
MangaCompactListModel(
|
||||
id = manga.id,
|
||||
title = manga.title,
|
||||
subtitle = manga.tags.joinToString { it.title },
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.koitharu.kotatsu.explore.ui.model.MangaSourceItem
|
||||
import org.koitharu.kotatsu.explore.ui.model.RecommendationsItem
|
||||
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaCompactListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
fun exploreButtonsAD(
|
||||
@@ -66,7 +66,7 @@ fun exploreRecommendationItemAD(
|
||||
{ layoutInflater, parent -> ItemRecommendationBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
val adapter = BaseListAdapter<MangaListModel>()
|
||||
val adapter = BaseListAdapter<MangaCompactListModel>()
|
||||
.addDelegate(ListItemType.MANGA_LIST, recommendationMangaItemAD(coil, itemClickListener, lifecycleOwner))
|
||||
binding.pager.adapter = adapter
|
||||
binding.pager.recyclerView?.isNestedScrollingEnabled = false
|
||||
@@ -81,7 +81,7 @@ fun recommendationMangaItemAD(
|
||||
coil: ImageLoader,
|
||||
itemClickListener: OnListItemClickListener<Manga>,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
) = adapterDelegateViewBinding<MangaListModel, MangaListModel, ItemRecommendationMangaBinding>(
|
||||
) = adapterDelegateViewBinding<MangaCompactListModel, MangaCompactListModel, ItemRecommendationMangaBinding>(
|
||||
{ layoutInflater, parent -> ItemRecommendationMangaBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.koitharu.kotatsu.explore.ui.model
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaCompactListModel
|
||||
|
||||
data class RecommendationsItem(
|
||||
val manga: List<MangaListModel>
|
||||
val manga: List<MangaCompactListModel>
|
||||
) : ListModel {
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
|
||||
@@ -24,13 +24,12 @@ import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID
|
||||
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
|
||||
import org.koitharu.kotatsu.history.domain.MarkAsReadUseCase
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.inject.Inject
|
||||
@@ -41,7 +40,7 @@ private const val PAGE_SIZE = 20
|
||||
class FavouritesListViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val repository: FavouritesRepository,
|
||||
private val listExtraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
private val markAsReadUseCase: MarkAsReadUseCase,
|
||||
settings: AppSettings,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
@@ -86,7 +85,7 @@ class FavouritesListViewModel @Inject constructor(
|
||||
|
||||
else -> {
|
||||
isReady.set(true)
|
||||
list.toUi(mode, listExtraProvider)
|
||||
mangaListMapper.toListModelList(list, mode)
|
||||
}
|
||||
}
|
||||
}.catch {
|
||||
|
||||
@@ -28,8 +28,8 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.history.domain.MarkAsReadUseCase
|
||||
import org.koitharu.kotatsu.history.domain.model.MangaWithHistory
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyHint
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
@@ -38,9 +38,6 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.TipModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toGridModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toListDetailedModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toListModel
|
||||
import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import java.time.Instant
|
||||
@@ -53,7 +50,7 @@ private const val PAGE_SIZE = 20
|
||||
class HistoryListViewModel @Inject constructor(
|
||||
private val repository: HistoryRepository,
|
||||
settings: AppSettings,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
private val localMangaRepository: LocalMangaRepository,
|
||||
private val markAsReadUseCase: MarkAsReadUseCase,
|
||||
networkState: NetworkState,
|
||||
@@ -203,11 +200,7 @@ class HistoryListViewModel @Inject constructor(
|
||||
prevHeader = header
|
||||
}
|
||||
}
|
||||
result += when (mode) {
|
||||
ListMode.LIST -> manga.toListModel(extraProvider)
|
||||
ListMode.DETAILED_LIST -> manga.toListDetailedModel(extraProvider)
|
||||
ListMode.GRID -> manga.toGridModel(extraProvider)
|
||||
}
|
||||
result += mangaListMapper.toListModel(manga, mode)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.koitharu.kotatsu.list.domain
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.ColorRes
|
||||
import dagger.Reusable
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class ListExtraProvider @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val settings: AppSettings,
|
||||
private val trackingRepository: TrackingRepository,
|
||||
private val historyRepository: HistoryRepository,
|
||||
) {
|
||||
|
||||
private val dict by lazy {
|
||||
context.resources.openRawResource(R.raw.tags_redlist).use {
|
||||
val set = HashSet<String>()
|
||||
it.bufferedReader().forEachLine { x ->
|
||||
val line = x.trim()
|
||||
if (line.isNotEmpty()) {
|
||||
set.add(line)
|
||||
}
|
||||
}
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCounter(mangaId: Long): Int {
|
||||
return if (settings.isTrackerEnabled) {
|
||||
trackingRepository.getNewChaptersCount(mangaId)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getProgress(mangaId: Long): Float {
|
||||
return if (settings.isReadingIndicatorsEnabled) {
|
||||
historyRepository.getProgress(mangaId)
|
||||
} else {
|
||||
PROGRESS_NONE
|
||||
}
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
fun getTagTint(tag: MangaTag): Int {
|
||||
return if (tag.title.lowercase() in dict) {
|
||||
R.color.warning
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package org.koitharu.kotatsu.list.domain
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.collection.MutableScatterSet
|
||||
import androidx.collection.ScatterSet
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaCompactListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaDetailedListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaGridModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MangaListMapper @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val settings: AppSettings,
|
||||
private val trackingRepository: TrackingRepository,
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val favouritesRepository: FavouritesRepository,
|
||||
) {
|
||||
|
||||
private val dict by lazy { readTagsDict(context) }
|
||||
|
||||
suspend fun toListModelList(manga: Collection<Manga>, mode: ListMode): List<MangaListModel> = manga.map {
|
||||
toListModel(it, mode)
|
||||
}
|
||||
|
||||
suspend fun toListModelList(
|
||||
destination: MutableCollection<in MangaListModel>,
|
||||
manga: Collection<Manga>,
|
||||
mode: ListMode
|
||||
) = manga.mapTo(destination) {
|
||||
toListModel(it, mode)
|
||||
}
|
||||
|
||||
suspend fun toListModel(manga: Manga, mode: ListMode): MangaListModel = when (mode) {
|
||||
ListMode.LIST -> toCompactListModel(manga)
|
||||
ListMode.DETAILED_LIST -> toDetailedListModel(manga)
|
||||
ListMode.GRID -> toGridModel(manga)
|
||||
}
|
||||
|
||||
suspend fun toCompactListModel(manga: Manga) = MangaCompactListModel(
|
||||
id = manga.id,
|
||||
title = manga.title,
|
||||
subtitle = manga.tags.joinToString(", ") { it.title },
|
||||
coverUrl = manga.coverUrl,
|
||||
manga = manga,
|
||||
counter = getCounter(manga.id),
|
||||
progress = getProgress(manga.id),
|
||||
)
|
||||
|
||||
suspend fun toDetailedListModel(manga: Manga) = MangaDetailedListModel(
|
||||
id = manga.id,
|
||||
title = manga.title,
|
||||
subtitle = manga.altTitle,
|
||||
coverUrl = manga.coverUrl,
|
||||
manga = manga,
|
||||
counter = getCounter(manga.id),
|
||||
progress = getProgress(manga.id),
|
||||
tags = mapTags(manga.tags),
|
||||
)
|
||||
|
||||
suspend fun toGridModel(manga: Manga) = MangaGridModel(
|
||||
id = manga.id,
|
||||
title = manga.title,
|
||||
coverUrl = manga.coverUrl,
|
||||
manga = manga,
|
||||
counter = getCounter(manga.id),
|
||||
progress = getProgress(manga.id),
|
||||
)
|
||||
|
||||
fun mapTags(tags: Collection<MangaTag>) = tags.map {
|
||||
ChipsView.ChipModel(
|
||||
tint = getTagTint(it),
|
||||
title = it.title,
|
||||
data = it,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun getCounter(mangaId: Long): Int {
|
||||
return if (settings.isTrackerEnabled) {
|
||||
trackingRepository.getNewChaptersCount(mangaId)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getProgress(mangaId: Long): Float {
|
||||
return if (settings.isReadingIndicatorsEnabled) {
|
||||
historyRepository.getProgress(mangaId)
|
||||
} else {
|
||||
PROGRESS_NONE
|
||||
}
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
private fun getTagTint(tag: MangaTag): Int {
|
||||
return if (tag.title.lowercase() in dict) {
|
||||
R.color.warning
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
private fun readTagsDict(context: Context): ScatterSet<String> =
|
||||
context.resources.openRawResource(R.raw.tags_redlist).use {
|
||||
val set = MutableScatterSet<String>()
|
||||
it.bufferedReader().forEachLine { x ->
|
||||
val line = x.trim()
|
||||
if (line.isNotEmpty()) {
|
||||
set.add(line)
|
||||
}
|
||||
}
|
||||
set.trim()
|
||||
set
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import coil.ImageLoader
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.browser.cloudflare.CaptchaNotifier
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -51,7 +50,7 @@ import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
||||
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.size.DynamicItemSizeResolver
|
||||
import org.koitharu.kotatsu.main.ui.MainActivity
|
||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||
@@ -281,7 +280,7 @@ abstract class MangaListFragment :
|
||||
return when (item.itemId) {
|
||||
R.id.action_select_all -> {
|
||||
val ids = listAdapter?.items?.mapNotNull {
|
||||
(it as? MangaItemModel)?.id
|
||||
(it as? MangaListModel)?.id
|
||||
} ?: return false
|
||||
selectionController?.addAll(ids)
|
||||
true
|
||||
@@ -327,7 +326,7 @@ abstract class MangaListFragment :
|
||||
val items = listAdapter?.items ?: return emptySet()
|
||||
val result = ArraySet<Manga>(checkedIds.size)
|
||||
for (item in items) {
|
||||
if (item is MangaItemModel && item.id in checkedIds) {
|
||||
if (item is MangaListModel && item.id in checkedIds) {
|
||||
result.add(item.manga)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration
|
||||
import org.koitharu.kotatsu.core.util.ext.getItem
|
||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
open class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() {
|
||||
@@ -37,7 +37,7 @@ open class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDec
|
||||
|
||||
override fun getItemId(parent: RecyclerView, child: View): Long {
|
||||
val holder = parent.getChildViewHolder(child) ?: return NO_ID
|
||||
val item = holder.getItem(MangaItemModel::class.java) ?: return NO_ID
|
||||
val item = holder.getItem(MangaListModel::class.java) ?: return NO_ID
|
||||
return item.id
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||
import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaDetailedListModel
|
||||
|
||||
fun mangaListDetailedItemAD(
|
||||
coil: ImageLoader,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
clickListener: MangaDetailsClickListener,
|
||||
) = adapterDelegateViewBinding<MangaListDetailedModel, ListModel, ItemMangaListDetailsBinding>(
|
||||
) = adapterDelegateViewBinding<MangaDetailedListModel, ListModel, ItemMangaListDetailsBinding>(
|
||||
{ inflater, parent -> ItemMangaListDetailsBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
@@ -15,14 +15,14 @@ import org.koitharu.kotatsu.core.util.ext.source
|
||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||
import org.koitharu.kotatsu.databinding.ItemMangaListBinding
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaCompactListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
fun mangaListItemAD(
|
||||
coil: ImageLoader,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
clickListener: OnListItemClickListener<Manga>,
|
||||
) = adapterDelegateViewBinding<MangaListModel, ListModel, ItemMangaListBinding>(
|
||||
) = adapterDelegateViewBinding<MangaCompactListModel, ListModel, ItemMangaListBinding>(
|
||||
{ inflater, parent -> ItemMangaListBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
@@ -3,74 +3,8 @@ package org.koitharu.kotatsu.list.ui.model
|
||||
import androidx.annotation.StringRes
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayIcon
|
||||
import org.koitharu.kotatsu.core.util.ext.ifZero
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
suspend fun Manga.toListModel(
|
||||
extraProvider: ListExtraProvider?
|
||||
) = MangaListModel(
|
||||
id = id,
|
||||
title = title,
|
||||
subtitle = tags.joinToString(", ") { it.title },
|
||||
coverUrl = coverUrl,
|
||||
manga = this,
|
||||
counter = extraProvider?.getCounter(id) ?: 0,
|
||||
progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE,
|
||||
)
|
||||
|
||||
suspend fun Manga.toListDetailedModel(
|
||||
extraProvider: ListExtraProvider?,
|
||||
) = MangaListDetailedModel(
|
||||
id = id,
|
||||
title = title,
|
||||
subtitle = altTitle,
|
||||
coverUrl = coverUrl,
|
||||
manga = this,
|
||||
counter = extraProvider?.getCounter(id) ?: 0,
|
||||
progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE,
|
||||
tags = tags.map {
|
||||
ChipsView.ChipModel(
|
||||
tint = extraProvider?.getTagTint(it) ?: 0,
|
||||
title = it.title,
|
||||
data = it,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
suspend fun Manga.toGridModel(
|
||||
extraProvider: ListExtraProvider?,
|
||||
) = MangaGridModel(
|
||||
id = id,
|
||||
title = title,
|
||||
coverUrl = coverUrl,
|
||||
manga = this,
|
||||
counter = extraProvider?.getCounter(id) ?: 0,
|
||||
progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE,
|
||||
)
|
||||
|
||||
suspend fun List<Manga>.toUi(
|
||||
mode: ListMode,
|
||||
extraProvider: ListExtraProvider,
|
||||
): List<MangaItemModel> = if (isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
toUi(ArrayList(size), mode, extraProvider)
|
||||
}
|
||||
|
||||
suspend fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
|
||||
destination: C,
|
||||
mode: ListMode,
|
||||
extraProvider: ListExtraProvider,
|
||||
): C = when (mode) {
|
||||
ListMode.LIST -> mapTo(destination) { it.toListModel(extraProvider) }
|
||||
ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(extraProvider) }
|
||||
ListMode.GRID -> mapTo(destination) { it.toGridModel(extraProvider) }
|
||||
}
|
||||
|
||||
fun Throwable.toErrorState(canRetry: Boolean = true, @StringRes secondaryAction: Int = 0) = ErrorState(
|
||||
exception = this,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.list.ui.model
|
||||
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
data class MangaCompactListModel(
|
||||
override val id: Long,
|
||||
override val title: String,
|
||||
val subtitle: String,
|
||||
override val coverUrl: String,
|
||||
override val manga: Manga,
|
||||
override val counter: Int,
|
||||
override val progress: Float,
|
||||
) : MangaListModel()
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.list.ui.model
|
||||
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
data class MangaListDetailedModel(
|
||||
data class MangaDetailedListModel(
|
||||
override val id: Long,
|
||||
override val title: String,
|
||||
val subtitle: String?,
|
||||
@@ -12,4 +12,4 @@ data class MangaListDetailedModel(
|
||||
override val counter: Int,
|
||||
override val progress: Float,
|
||||
val tags: List<ChipsView.ChipModel>,
|
||||
) : MangaItemModel()
|
||||
) : MangaListModel()
|
||||
@@ -9,4 +9,4 @@ data class MangaGridModel(
|
||||
override val manga: Manga,
|
||||
override val counter: Int,
|
||||
override val progress: Float,
|
||||
) : MangaItemModel()
|
||||
) : MangaListModel()
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.koitharu.kotatsu.list.ui.model
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
|
||||
sealed class MangaItemModel : ListModel {
|
||||
|
||||
abstract val id: Long
|
||||
abstract val manga: Manga
|
||||
abstract val title: String
|
||||
abstract val coverUrl: String
|
||||
abstract val counter: Int
|
||||
abstract val progress: Float
|
||||
|
||||
val source: MangaSource
|
||||
get() = manga.source
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is MangaItemModel && other.javaClass == javaClass && id == other.id
|
||||
}
|
||||
|
||||
override fun getChangePayload(previousState: ListModel): Any? {
|
||||
return when {
|
||||
previousState !is MangaItemModel -> super.getChangePayload(previousState)
|
||||
progress != previousState.progress -> ListModelDiffCallback.PAYLOAD_PROGRESS_CHANGED
|
||||
counter != previousState.counter -> ListModelDiffCallback.PAYLOAD_ANYTHING_CHANGED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,31 @@
|
||||
package org.koitharu.kotatsu.list.ui.model
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
|
||||
data class MangaListModel(
|
||||
override val id: Long,
|
||||
override val title: String,
|
||||
val subtitle: String,
|
||||
override val coverUrl: String,
|
||||
override val manga: Manga,
|
||||
override val counter: Int,
|
||||
override val progress: Float,
|
||||
) : MangaItemModel()
|
||||
sealed class MangaListModel : ListModel {
|
||||
|
||||
abstract val id: Long
|
||||
abstract val manga: Manga
|
||||
abstract val title: String
|
||||
abstract val coverUrl: String
|
||||
abstract val counter: Int
|
||||
abstract val progress: Float
|
||||
|
||||
val source: MangaSource
|
||||
get() = manga.source
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is MangaListModel && other.javaClass == javaClass && id == other.id
|
||||
}
|
||||
|
||||
override fun getChangePayload(previousState: ListModel): Any? {
|
||||
return when {
|
||||
previousState !is MangaListModel -> super.getChangePayload(previousState)
|
||||
progress != previousState.progress -> ListModelDiffCallback.PAYLOAD_PROGRESS_CHANGED
|
||||
counter != previousState.counter -> ListModelDiffCallback.PAYLOAD_ANYTHING_CHANGED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,18 +25,17 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.core.util.ext.sanitize
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.history.data.PROGRESS_NONE
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class PreviewViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
private val repositoryFactory: MangaRepository.Factory,
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val imageGetter: Html.ImageGetter,
|
||||
@@ -81,13 +80,7 @@ class PreviewViewModel @Inject constructor(
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), null)
|
||||
|
||||
val tagsChips = manga.map {
|
||||
it.tags.map { tag ->
|
||||
ChipsView.ChipModel(
|
||||
title = tag.title,
|
||||
tint = extraProvider.getTagTint(tag),
|
||||
data = tag,
|
||||
)
|
||||
}
|
||||
mangaListMapper.mapTags(it.tags)
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
|
||||
|
||||
init {
|
||||
|
||||
@@ -16,10 +16,10 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.TipModel
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageChanges
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
@@ -35,7 +35,7 @@ class LocalListViewModel @Inject constructor(
|
||||
filter: FilterCoordinator,
|
||||
private val settings: AppSettings,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
listExtraProvider: ListExtraProvider,
|
||||
mangaListMapper: MangaListMapper,
|
||||
private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase,
|
||||
exploreRepository: ExploreRepository,
|
||||
@LocalStorageChanges private val localStorageChanges: SharedFlow<LocalManga?>,
|
||||
@@ -46,7 +46,7 @@ class LocalListViewModel @Inject constructor(
|
||||
mangaRepositoryFactory,
|
||||
filter,
|
||||
settings,
|
||||
listExtraProvider,
|
||||
mangaListMapper,
|
||||
downloadScheduler,
|
||||
exploreRepository,
|
||||
sourcesRepository,
|
||||
@@ -70,7 +70,7 @@ class LocalListViewModel @Inject constructor(
|
||||
return
|
||||
}
|
||||
for (item in list) {
|
||||
if (item !is MangaItemModel) {
|
||||
if (item !is MangaListModel) {
|
||||
continue
|
||||
}
|
||||
val file = item.manga.url.toUriOrNull()?.toFileOrNull() ?: continue
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
|
||||
import org.koitharu.kotatsu.filter.ui.MangaFilter
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
@@ -40,7 +40,6 @@ import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.parsers.exception.NotFoundException
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaListFilter
|
||||
@@ -55,7 +54,7 @@ open class RemoteListViewModel @Inject constructor(
|
||||
mangaRepositoryFactory: MangaRepository.Factory,
|
||||
private val filter: FilterCoordinator,
|
||||
settings: AppSettings,
|
||||
listExtraProvider: ListExtraProvider,
|
||||
mangaListMapper: MangaListMapper,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
private val exploreRepository: ExploreRepository,
|
||||
sourcesRepository: MangaSourcesRepository,
|
||||
@@ -96,7 +95,7 @@ open class RemoteListViewModel @Inject constructor(
|
||||
list == null -> add(LoadingState)
|
||||
list.isEmpty() -> add(createEmptyState(canResetFilter = header.value.isFilterApplied))
|
||||
else -> {
|
||||
list.toUi(this, mode, listExtraProvider)
|
||||
mangaListMapper.toListModelList(this, list, mode)
|
||||
when {
|
||||
error != null -> add(error.toErrorFooter())
|
||||
hasNext -> add(LoadingFooter())
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.core.util.ext.sizeOrZero
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
@@ -28,7 +28,6 @@ import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaListFilter
|
||||
import javax.inject.Inject
|
||||
@@ -38,7 +37,7 @@ class SearchViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
repositoryFactory: MangaRepository.Factory,
|
||||
settings: AppSettings,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
) : MangaListViewModel(settings, downloadScheduler) {
|
||||
|
||||
@@ -69,7 +68,7 @@ class SearchViewModel @Inject constructor(
|
||||
|
||||
else -> {
|
||||
val result = ArrayList<ListModel>(list.size + 1)
|
||||
list.toUi(result, mode, extraProvider)
|
||||
mangaListMapper.toListModelList(result, list, mode)
|
||||
when {
|
||||
error != null -> result += error.toErrorFooter()
|
||||
hasNext -> result += LoadingFooter()
|
||||
|
||||
@@ -2,13 +2,13 @@ package org.koitharu.kotatsu.search.ui.multi
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
|
||||
data class MultiSearchListModel(
|
||||
val source: MangaSource,
|
||||
val hasMore: Boolean,
|
||||
val list: List<MangaItemModel>,
|
||||
val list: List<MangaListModel>,
|
||||
val error: Throwable?,
|
||||
) : ListModel {
|
||||
|
||||
|
||||
@@ -29,12 +29,11 @@ import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaListFilter
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
@@ -46,7 +45,7 @@ private const val MIN_HAS_MORE_ITEMS = 8
|
||||
@HiltViewModel
|
||||
class MultiSearchViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
private val mangaRepositoryFactory: MangaRepository.Factory,
|
||||
private val downloadScheduler: DownloadWorker.Scheduler,
|
||||
private val sourcesRepository: MangaSourcesRepository,
|
||||
@@ -121,8 +120,10 @@ class MultiSearchViewModel @Inject constructor(
|
||||
launch {
|
||||
val item = runCatchingCancellable {
|
||||
semaphore.withPermit {
|
||||
repository.getList(offset = 0, filter = MangaListFilter.Search(q))
|
||||
.toUi(ListMode.GRID, extraProvider)
|
||||
mangaListMapper.toListModelList(
|
||||
manga = repository.getList(offset = 0, filter = MangaListFilter.Search(q)),
|
||||
mode = ListMode.GRID,
|
||||
)
|
||||
}
|
||||
}.fold(
|
||||
onSuccess = { list ->
|
||||
|
||||
@@ -14,12 +14,11 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.onFirst
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toUi
|
||||
import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -27,7 +26,7 @@ import javax.inject.Inject
|
||||
class SuggestionsViewModel @Inject constructor(
|
||||
repository: SuggestionRepository,
|
||||
settings: AppSettings,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
private val suggestionsScheduler: SuggestionsWorker.Scheduler,
|
||||
) : MangaListViewModel(settings, downloadScheduler) {
|
||||
@@ -49,7 +48,7 @@ class SuggestionsViewModel @Inject constructor(
|
||||
),
|
||||
)
|
||||
|
||||
else -> list.toUi(mode, extraProvider)
|
||||
else -> mangaListMapper.toListModelList(list, mode)
|
||||
}
|
||||
}.onStart {
|
||||
loadingCounter.increment()
|
||||
|
||||
@@ -20,12 +20,11 @@ import org.koitharu.kotatsu.core.ui.model.DateTimeAgo
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.calculateTimeAgo
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toGridModel
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem
|
||||
import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem
|
||||
@@ -42,7 +41,7 @@ class FeedViewModel @Inject constructor(
|
||||
private val settings: AppSettings,
|
||||
private val repository: TrackingRepository,
|
||||
private val scheduler: TrackWorker.Scheduler,
|
||||
private val listExtraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val limit = MutableStateFlow(PAGE_SIZE)
|
||||
@@ -135,7 +134,7 @@ class FeedViewModel @Inject constructor(
|
||||
null
|
||||
} else {
|
||||
UpdatedMangaHeader(
|
||||
mangaList.map { it.manga.toGridModel(listExtraProvider) },
|
||||
mangaList.map { mangaListMapper.toGridModel(it.manga) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package org.koitharu.kotatsu.tracker.ui.feed.model
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaListModel
|
||||
|
||||
data class UpdatedMangaHeader(
|
||||
val list: List<MangaItemModel>,
|
||||
val list: List<MangaListModel>,
|
||||
) : ListModel {
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
|
||||
@@ -17,16 +17,13 @@ import org.koitharu.kotatsu.core.ui.model.DateTimeAgo
|
||||
import org.koitharu.kotatsu.core.util.ext.calculateTimeAgo
|
||||
import org.koitharu.kotatsu.core.util.ext.onFirst
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.domain.MangaListMapper
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorState
|
||||
import org.koitharu.kotatsu.list.ui.model.toGridModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toListDetailedModel
|
||||
import org.koitharu.kotatsu.list.ui.model.toListModel
|
||||
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import org.koitharu.kotatsu.tracker.domain.model.MangaTracking
|
||||
import javax.inject.Inject
|
||||
@@ -35,7 +32,7 @@ import javax.inject.Inject
|
||||
class UpdatesViewModel @Inject constructor(
|
||||
private val repository: TrackingRepository,
|
||||
settings: AppSettings,
|
||||
private val extraProvider: ListExtraProvider,
|
||||
private val mangaListMapper: MangaListMapper,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
) : MangaListViewModel(settings, downloadScheduler) {
|
||||
|
||||
@@ -93,11 +90,7 @@ class UpdatesViewModel @Inject constructor(
|
||||
prevHeader = header
|
||||
}
|
||||
}
|
||||
result += when (mode) {
|
||||
ListMode.LIST -> item.manga.toListModel(extraProvider)
|
||||
ListMode.DETAILED_LIST -> item.manga.toListDetailedModel(extraProvider)
|
||||
ListMode.GRID -> item.manga.toGridModel(extraProvider)
|
||||
}
|
||||
result += mangaListMapper.toListModel(item.manga, mode)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user