Highlight suspicious genres

This commit is contained in:
Koitharu
2023-02-25 17:15:07 +02:00
parent 5d2395b569
commit 9adf209445
17 changed files with 117 additions and 34 deletions

View File

@@ -3,15 +3,16 @@ package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View.OnClickListener import android.view.View.OnClickListener
import androidx.annotation.DrawableRes import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.core.view.children import androidx.core.view.children
import com.google.android.material.R as materialR
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipDrawable
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.ext.castOrNull import org.koitharu.kotatsu.utils.ext.castOrNull
import org.koitharu.kotatsu.utils.ext.getThemeColorStateList import org.koitharu.kotatsu.utils.ext.getThemeColorStateList
import com.google.android.material.R as materialR
class ChipsView @JvmOverloads constructor( class ChipsView @JvmOverloads constructor(
context: Context, context: Context,
@@ -75,12 +76,12 @@ class ChipsView @JvmOverloads constructor(
private fun bindChip(chip: Chip, model: ChipModel) { private fun bindChip(chip: Chip, model: ChipModel) {
chip.text = model.title chip.text = model.title
if (model.icon == 0) { val tint = if (model.tint == 0) {
chip.isChipIconVisible = false null
} else { } else {
chip.isChipIconVisible = true ContextCompat.getColorStateList(context, model.tint)
chip.setChipIconResource(model.icon)
} }
chip.buttonTintList = tint
chip.isClickable = onChipClickListener != null || model.isCheckable chip.isClickable = onChipClickListener != null || model.isCheckable
chip.isCheckable = model.isCheckable chip.isCheckable = model.isCheckable
chip.isChecked = model.isChecked chip.isChecked = model.isChecked
@@ -92,6 +93,7 @@ class ChipsView @JvmOverloads constructor(
val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_Kotatsu_Chip) val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_Kotatsu_Chip)
chip.setChipDrawable(drawable) chip.setChipDrawable(drawable)
chip.isCheckedIconVisible = true chip.isCheckedIconVisible = true
chip.isChipIconVisible = false
chip.setCheckedIconResource(R.drawable.ic_check) chip.setCheckedIconResource(R.drawable.ic_check)
chip.checkedIconTint = context.getThemeColorStateList(materialR.attr.colorControlNormal) chip.checkedIconTint = context.getThemeColorStateList(materialR.attr.colorControlNormal)
chip.isCloseIconVisible = onChipCloseClickListener != null chip.isCloseIconVisible = onChipCloseClickListener != null
@@ -113,7 +115,7 @@ class ChipsView @JvmOverloads constructor(
} }
class ChipModel( class ChipModel(
@DrawableRes val icon: Int, @ColorRes val tint: Int,
val title: CharSequence, val title: CharSequence,
val isCheckable: Boolean, val isCheckable: Boolean,
val isChecked: Boolean, val isChecked: Boolean,
@@ -126,7 +128,7 @@ class ChipsView @JvmOverloads constructor(
other as ChipModel other as ChipModel
if (icon != other.icon) return false if (tint != other.tint) return false
if (title != other.title) return false if (title != other.title) return false
if (isCheckable != other.isCheckable) return false if (isCheckable != other.isCheckable) return false
if (isChecked != other.isChecked) return false if (isChecked != other.isChecked) return false
@@ -136,7 +138,7 @@ class ChipsView @JvmOverloads constructor(
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = icon var result = tint.hashCode()
result = 31 * result + title.hashCode() result = 31 * result + title.hashCode()
result = 31 * result + isCheckable.hashCode() result = 31 * result + isCheckable.hashCode()
result = 31 * result + isChecked.hashCode() result = 31 * result + isChecked.hashCode()

View File

@@ -0,0 +1,26 @@
package org.koitharu.kotatsu.core.parser
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.parsers.model.MangaTag
import javax.inject.Inject
@Reusable
class MangaTagHighlighter @Inject constructor(
@ApplicationContext context: Context,
) {
private val dict = context.resources.getStringArray(R.array.genres_warnlist).toSet()
@ColorRes
fun getTint(tag: MangaTag): Int {
return if (tag.title.lowercase() in dict) {
R.color.warning
} else {
0
}
}
}

View File

@@ -26,6 +26,7 @@ import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration
import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.Bookmark
import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.databinding.FragmentDetailsBinding import org.koitharu.kotatsu.databinding.FragmentDetailsBinding
import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.ChapterListItem
import org.koitharu.kotatsu.details.ui.model.HistoryInfo import org.koitharu.kotatsu.details.ui.model.HistoryInfo
@@ -69,6 +70,9 @@ class DetailsFragment :
@Inject @Inject
lateinit var coil: ImageLoader lateinit var coil: ImageLoader
@Inject
lateinit var tagHighlighter: MangaTagHighlighter
private val viewModel by activityViewModels<DetailsViewModel>() private val viewModel by activityViewModels<DetailsViewModel>()
override fun onInflateView( override fun onInflateView(
@@ -321,7 +325,7 @@ class DetailsFragment :
manga.tags.map { tag -> manga.tags.map { tag ->
ChipsView.ChipModel( ChipsView.ChipModel(
title = tag.title, title = tag.title,
icon = 0, tint = tagHighlighter.getTint(tag),
data = tag, data = tag,
isCheckable = false, isCheckable = false,
isChecked = false, isChecked = false,

View File

@@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.base.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
@@ -36,6 +37,7 @@ class FavouritesListViewModel @AssistedInject constructor(
private val trackingRepository: TrackingRepository, private val trackingRepository: TrackingRepository,
private val historyRepository: HistoryRepository, private val historyRepository: HistoryRepository,
private val settings: AppSettings, private val settings: AppSettings,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings), ListExtraProvider { ) : MangaListViewModel(settings), ListExtraProvider {
var categoryName: String? = null var categoryName: String? = null
@@ -71,7 +73,7 @@ class FavouritesListViewModel @AssistedInject constructor(
), ),
) )
else -> list.toUi(mode, this) else -> list.toUi(mode, this, tagHighlighter)
} }
}.catch { }.catch {
emit(listOf(it.toErrorState(canRetry = false))) emit(listOf(it.toErrorState(canRetry = false)))

View File

@@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.base.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsFlow
@@ -38,6 +39,7 @@ class HistoryListViewModel @Inject constructor(
private val repository: HistoryRepository, private val repository: HistoryRepository,
private val settings: AppSettings, private val settings: AppSettings,
private val trackingRepository: TrackingRepository, private val trackingRepository: TrackingRepository,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings) { ) : MangaListViewModel(settings) {
val isGroupingEnabled = MutableLiveData<Boolean>() val isGroupingEnabled = MutableLiveData<Boolean>()
@@ -118,7 +120,7 @@ class HistoryListViewModel @Inject constructor(
val percent = if (showPercent) history.percent else PROGRESS_NONE val percent = if (showPercent) history.percent else PROGRESS_NONE
result += when (mode) { result += when (mode) {
ListMode.LIST -> manga.toListModel(counter, percent) ListMode.LIST -> manga.toListModel(counter, percent)
ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent) ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent, tagHighlighter)
ListMode.GRID -> manga.toGridModel(counter, percent) ListMode.GRID -> manga.toGridModel(counter, percent)
} }
} }

View File

@@ -4,6 +4,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.domain.ListExtraProvider
@@ -13,7 +14,10 @@ import org.koitharu.kotatsu.utils.ext.ifZero
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.net.UnknownHostException import java.net.UnknownHostException
fun Manga.toListModel(counter: Int, progress: Float) = MangaListModel( fun Manga.toListModel(
counter: Int,
progress: Float,
) = MangaListModel(
id = id, id = id,
title = title, title = title,
subtitle = tags.joinToString(", ") { it.title }, subtitle = tags.joinToString(", ") { it.title },
@@ -23,7 +27,11 @@ fun Manga.toListModel(counter: Int, progress: Float) = MangaListModel(
progress = progress, progress = progress,
) )
fun Manga.toListDetailedModel(counter: Int, progress: Float) = MangaListDetailedModel( fun Manga.toListDetailedModel(
counter: Int,
progress: Float,
tagHighlighter: MangaTagHighlighter?,
) = MangaListDetailedModel(
id = id, id = id,
title = title, title = title,
subtitle = altTitle, subtitle = altTitle,
@@ -31,7 +39,15 @@ fun Manga.toListDetailedModel(counter: Int, progress: Float) = MangaListDetailed
manga = this, manga = this,
counter = counter, counter = counter,
progress = progress, progress = progress,
tags = tags.map { ChipsView.ChipModel(0, it.title, false, false, it) }, tags = tags.map {
ChipsView.ChipModel(
tint = tagHighlighter?.getTint(it) ?: 0,
title = it.title,
isCheckable = false,
isChecked = false,
data = it,
)
},
) )
fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel( fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel(
@@ -46,18 +62,21 @@ fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel(
suspend fun List<Manga>.toUi( suspend fun List<Manga>.toUi(
mode: ListMode, mode: ListMode,
extraProvider: ListExtraProvider, extraProvider: ListExtraProvider,
): List<MangaItemModel> = toUi(ArrayList(size), mode, extraProvider) tagHighlighter: MangaTagHighlighter?,
): List<MangaItemModel> = toUi(ArrayList(size), mode, extraProvider, tagHighlighter)
fun List<Manga>.toUi( fun List<Manga>.toUi(
mode: ListMode, mode: ListMode,
): List<MangaItemModel> = toUi(ArrayList(size), mode) tagHighlighter: MangaTagHighlighter?,
): List<MangaItemModel> = toUi(ArrayList(size), mode, tagHighlighter)
fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi( fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
destination: C, destination: C,
mode: ListMode, mode: ListMode,
tagHighlighter: MangaTagHighlighter?,
): C = when (mode) { ): C = when (mode) {
ListMode.LIST -> mapTo(destination) { it.toListModel(0, PROGRESS_NONE) } ListMode.LIST -> mapTo(destination) { it.toListModel(0, PROGRESS_NONE) }
ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(0, PROGRESS_NONE) } ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(0, PROGRESS_NONE, tagHighlighter) }
ListMode.GRID -> mapTo(destination) { it.toGridModel(0, PROGRESS_NONE) } ListMode.GRID -> mapTo(destination) { it.toGridModel(0, PROGRESS_NONE) }
} }
@@ -65,13 +84,14 @@ suspend fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
destination: C, destination: C,
mode: ListMode, mode: ListMode,
extraProvider: ListExtraProvider, extraProvider: ListExtraProvider,
tagHighlighter: MangaTagHighlighter?,
): C = when (mode) { ): C = when (mode) {
ListMode.LIST -> mapTo(destination) { ListMode.LIST -> mapTo(destination) {
it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
} }
ListMode.DETAILED_LIST -> mapTo(destination) { ListMode.DETAILED_LIST -> mapTo(destination) {
it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id), tagHighlighter)
} }
ListMode.GRID -> mapTo(destination) { ListMode.GRID -> mapTo(destination) {

View File

@@ -16,6 +16,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.download.ui.service.DownloadService import org.koitharu.kotatsu.download.ui.service.DownloadService
import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.HistoryRepository
@@ -46,6 +47,7 @@ class LocalListViewModel @Inject constructor(
private val historyRepository: HistoryRepository, private val historyRepository: HistoryRepository,
private val trackingRepository: TrackingRepository, private val trackingRepository: TrackingRepository,
private val settings: AppSettings, private val settings: AppSettings,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings), ListExtraProvider { ) : MangaListViewModel(settings), ListExtraProvider {
val onMangaRemoved = SingleLiveEvent<Unit>() val onMangaRemoved = SingleLiveEvent<Unit>()
@@ -76,7 +78,7 @@ class LocalListViewModel @Inject constructor(
else -> buildList(list.size + 1) { else -> buildList(list.size + 1) {
add(createHeader(list, tags, order)) add(createHeader(list, tags, order))
list.toUi(this, mode, this@LocalListViewModel) list.toUi(this, mode, this@LocalListViewModel, tagHighlighter)
} }
} }
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
@@ -170,7 +172,7 @@ class LocalListViewModel @Inject constructor(
val chips = LinkedList<ChipsView.ChipModel>() val chips = LinkedList<ChipsView.ChipModel>()
for ((tag, _) in topTags) { for ((tag, _) in topTags) {
val model = ChipsView.ChipModel( val model = ChipsView.ChipModel(
icon = 0, tint = 0,
title = tag.title, title = tag.title,
isCheckable = true, isCheckable = true,
isChecked = tag in selectedTags, isChecked = tag in selectedTags,

View File

@@ -19,6 +19,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.domain.MangaDataRepository
import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.MangaListViewModel
@@ -49,6 +50,7 @@ class RemoteListViewModel @AssistedInject constructor(
private val searchRepository: MangaSearchRepository, private val searchRepository: MangaSearchRepository,
settings: AppSettings, settings: AppSettings,
dataRepository: MangaDataRepository, dataRepository: MangaDataRepository,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings), OnFilterChangedListener { ) : MangaListViewModel(settings), OnFilterChangedListener {
private val repository = mangaRepositoryFactory.create(source) as RemoteMangaRepository private val repository = mangaRepositoryFactory.create(source) as RemoteMangaRepository
@@ -75,7 +77,7 @@ class RemoteListViewModel @AssistedInject constructor(
list == null -> add(LoadingState) list == null -> add(LoadingState)
list.isEmpty() -> add(createEmptyState(header.hasSelectedTags)) list.isEmpty() -> add(createEmptyState(header.hasSelectedTags))
else -> { else -> {
list.toUi(this, mode) list.toUi(this, mode, tagHighlighter)
when { when {
error != null -> add(error.toErrorFooter()) error != null -> add(error.toErrorFooter())
hasNext -> add(LoadingFooter) hasNext -> add(LoadingFooter)
@@ -192,7 +194,7 @@ class RemoteListViewModel @AssistedInject constructor(
val result = LinkedList<ChipsView.ChipModel>() val result = LinkedList<ChipsView.ChipModel>()
for (tag in tags) { for (tag in tags) {
val model = ChipsView.ChipModel( val model = ChipsView.ChipModel(
icon = 0, tint = 0,
title = tag.title, title = tag.title,
isCheckable = true, isCheckable = true,
isChecked = selectedTags.remove(tag), isChecked = selectedTags.remove(tag),
@@ -206,7 +208,7 @@ class RemoteListViewModel @AssistedInject constructor(
} }
for (tag in selectedTags) { for (tag in selectedTags) {
val model = ChipsView.ChipModel( val model = ChipsView.ChipModel(
icon = 0, tint = 0,
title = tag.title, title = tag.title,
isCheckable = true, isCheckable = true,
isChecked = true, isChecked = true,

View File

@@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.EmptyState
@@ -29,6 +30,7 @@ class SearchViewModel @AssistedInject constructor(
@Assisted private val query: String, @Assisted private val query: String,
repositoryFactory: MangaRepository.Factory, repositoryFactory: MangaRepository.Factory,
settings: AppSettings, settings: AppSettings,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings) { ) : MangaListViewModel(settings) {
private val repository = repositoryFactory.create(source) private val repository = repositoryFactory.create(source)
@@ -57,7 +59,7 @@ class SearchViewModel @AssistedInject constructor(
else -> { else -> {
val result = ArrayList<ListModel>(list.size + 1) val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode) list.toUi(result, mode, tagHighlighter)
when { when {
error != null -> result += error.toErrorFooter() error != null -> result += error.toErrorFooter()
hasNext -> result += LoadingFooter hasNext -> result += LoadingFooter

View File

@@ -6,7 +6,12 @@ import androidx.lifecycle.viewModelScope
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import kotlinx.coroutines.* import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
@@ -16,7 +21,12 @@ import org.koitharu.kotatsu.core.exceptions.CompositeException
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.list.ui.model.* 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.toErrorState
import org.koitharu.kotatsu.list.ui.model.toUi
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
@@ -104,7 +114,7 @@ class MultiSearchViewModel @AssistedInject constructor(
async(dispatcher) { async(dispatcher) {
runCatchingCancellable { runCatchingCancellable {
val list = mangaRepositoryFactory.create(source).getList(offset = 0, query = q) val list = mangaRepositoryFactory.create(source).getList(offset = 0, query = q)
.toUi(ListMode.GRID) .toUi(ListMode.GRID, null)
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
MultiSearchListModel(source, list.size > MIN_HAS_MORE_ITEMS, list) MultiSearchListModel(source, list.size > MIN_HAS_MORE_ITEMS, list)
} else { } else {

View File

@@ -134,7 +134,7 @@ class SearchSuggestionViewModel @Inject constructor(
private fun mapTags(tags: List<MangaTag>): List<ChipsView.ChipModel> = tags.map { tag -> private fun mapTags(tags: List<MangaTag>): List<ChipsView.ChipModel> = tags.map { tag ->
ChipsView.ChipModel( ChipsView.ChipModel(
icon = 0, tint = 0,
title = tag.title, title = tag.title,
data = tag, data = tag,
isCheckable = false, isCheckable = false,

View File

@@ -236,7 +236,7 @@ class ShelfViewModel @Inject constructor(
return return
} }
destination += ShelfSectionModel.Local( destination += ShelfSectionModel.Local(
items = local.toUi(ListMode.GRID, this), items = local.toUi(ListMode.GRID, this, null),
showAllButtonText = R.string.show_all, showAllButtonText = R.string.show_all,
) )
} }
@@ -251,7 +251,7 @@ class ShelfViewModel @Inject constructor(
for ((category, list) in favourites) { for ((category, list) in favourites) {
if (list.isNotEmpty()) { if (list.isNotEmpty()) {
destination += ShelfSectionModel.Favourites( destination += ShelfSectionModel.Favourites(
items = list.toUi(ListMode.GRID, this), items = list.toUi(ListMode.GRID, this, null),
category = category, category = category,
showAllButtonText = R.string.show_all, showAllButtonText = R.string.show_all,
) )

View File

@@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.EmptyState
@@ -22,6 +23,7 @@ import javax.inject.Inject
class SuggestionsViewModel @Inject constructor( class SuggestionsViewModel @Inject constructor(
repository: SuggestionRepository, repository: SuggestionRepository,
settings: AppSettings, settings: AppSettings,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings) { ) : MangaListViewModel(settings) {
override val content = combine( override val content = combine(
@@ -38,7 +40,7 @@ class SuggestionsViewModel @Inject constructor(
), ),
) )
else -> list.toUi(mode) else -> list.toUi(mode, tagHighlighter)
} }
}.onStart { }.onStart {
loadingCounter.increment() loadingCounter.increment()

View File

@@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.MangaTagHighlighter
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.HistoryRepository
@@ -30,6 +31,7 @@ class UpdatesViewModel @Inject constructor(
private val repository: TrackingRepository, private val repository: TrackingRepository,
private val settings: AppSettings, private val settings: AppSettings,
private val historyRepository: HistoryRepository, private val historyRepository: HistoryRepository,
private val tagHighlighter: MangaTagHighlighter,
) : MangaListViewModel(settings) { ) : MangaListViewModel(settings) {
override val content = combine( override val content = combine(
@@ -69,7 +71,7 @@ class UpdatesViewModel @Inject constructor(
val percent = if (showPercent) historyRepository.getProgress(manga.id) else PROGRESS_NONE val percent = if (showPercent) historyRepository.getProgress(manga.id) else PROGRESS_NONE
when (mode) { when (mode) {
ListMode.LIST -> manga.toListModel(counter, percent) ListMode.LIST -> manga.toListModel(counter, percent)
ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent) ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent, tagHighlighter)
ListMode.GRID -> manga.toGridModel(counter, percent) ListMode.GRID -> manga.toGridModel(counter, percent)
} }
} }

View File

@@ -9,5 +9,5 @@
<color name="selector_foreground">#29FFFFFF</color> <color name="selector_foreground">#29FFFFFF</color>
<color name="divider_default">#1FFFFFFF</color> <color name="divider_default">#1FFFFFFF</color>
<color name="status_bar_incognito">#260052</color> <color name="status_bar_incognito">#260052</color>
<color name="warning">#EF6C00</color>
</resources> </resources>

View File

@@ -22,4 +22,5 @@
<color name="selector_foreground">#29000000</color> <color name="selector_foreground">#29000000</color>
<color name="divider_default">#1F000000</color> <color name="divider_default">#1F000000</color>
<color name="status_bar_incognito">#334800E0</color> <color name="status_bar_incognito">#334800E0</color>
<color name="warning">#FFA726</color>
</resources> </resources>

View File

@@ -38,4 +38,10 @@
<item>2</item> <item>2</item>
<item>0</item> <item>0</item>
</string-array> </string-array>
<string-array name="genres_warnlist" translatable="false">
<item>yaoi</item>
<item>яой</item>
<item>yuri</item>
<item>юри</item>
</string-array>
</resources> </resources>