Fix override applying

This commit is contained in:
Koitharu
2025-07-13 11:07:00 +03:00
parent fe3f95d160
commit 5a368b27bb
20 changed files with 89 additions and 79 deletions

View File

@@ -11,7 +11,6 @@ import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.widget.TooltipCompat
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
import androidx.core.text.method.LinkMovementMethodCompat
@@ -261,7 +260,7 @@ class DetailsActivity :
R.id.button_scrobbling_more -> {
router.showScrobblingSelectorSheet(
manga = viewModel.getMangaOrNull() ?: return,
scrobblerService = viewModel.scrobblingInfo.value.firstOrNull()?.scrobbler
scrobblerService = viewModel.scrobblingInfo.value.firstOrNull()?.scrobbler,
)
}
@@ -390,7 +389,7 @@ class DetailsActivity :
mangaGridItemAD(
sizeResolver = StaticItemSizeResolver(resources.getDimensionPixelSize(R.dimen.smaller_grid_width)),
) { item, view ->
router.openDetails(item)
router.openDetails(item.toMangaWithOverride())
},
).also { rv.adapter = it }
adapter.items = related

View File

@@ -198,11 +198,9 @@ class ExploreViewModel @Inject constructor(
private fun List<Manga>.toRecommendationList() = map { manga ->
MangaCompactListModel(
id = manga.id,
title = manga.title,
subtitle = manga.tags.joinToString { it.title },
coverUrl = manga.coverUrl,
manga = manga,
override = null,
subtitle = manga.tags.joinToString { it.title },
counter = 0,
)
}

View File

@@ -23,8 +23,9 @@ import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.local.data.index.LocalMangaIndex
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem
import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem
import javax.inject.Inject
@Reusable
@@ -77,6 +78,14 @@ class MangaListMapper @Inject constructor(
override = dataRepository.getOverride(manga.id),
)
suspend fun toFeedItem(logItem: TrackingLogItem) = FeedItem(
id = logItem.id,
override = dataRepository.getOverride(logItem.manga.id),
count = logItem.chapters.size,
manga = logItem.manga,
isNew = logItem.isNew,
)
fun mapTags(tags: Collection<MangaTag>) = tags.map {
ChipsView.ChipModel(
tint = getTagTint(it),
@@ -90,11 +99,9 @@ class MangaListMapper @Inject constructor(
@Options options: Int,
override: MangaOverride?,
) = MangaCompactListModel(
id = manga.id,
title = override?.title.ifNullOrEmpty { manga.title },
subtitle = manga.tags.joinToString(", ") { it.title },
coverUrl = override?.coverUrl.ifNullOrEmpty { manga.coverUrl },
manga = manga,
override = override,
subtitle = manga.tags.joinToString(", ") { it.title },
counter = getCounter(manga.id, options),
)
@@ -103,11 +110,9 @@ class MangaListMapper @Inject constructor(
@Options options: Int,
override: MangaOverride?,
) = MangaDetailedListModel(
id = manga.id,
title = override?.title.ifNullOrEmpty { manga.title },
subtitle = manga.altTitles.firstOrNull(),
coverUrl = override?.coverUrl.ifNullOrEmpty { manga.coverUrl },
manga = manga,
override = override,
counter = getCounter(manga.id, options),
progress = getProgress(manga.id, options),
isFavorite = isFavorite(manga.id, options),
@@ -120,10 +125,8 @@ class MangaListMapper @Inject constructor(
@Options options: Int,
override: MangaOverride?
) = MangaGridModel(
id = manga.id,
title = override?.title.ifNullOrEmpty { manga.title },
coverUrl = override?.coverUrl.ifNullOrEmpty { manga.coverUrl },
manga = manga,
override = override,
counter = getCounter(manga.id, options),
progress = getProgress(manga.id, options),
isFavorite = isFavorite(manga.id, options),

View File

@@ -153,19 +153,20 @@ abstract class MangaListFragment :
super.onDestroyView()
}
override fun onItemClick(item: Manga, view: View) {
override fun onItemClick(item: MangaListModel, view: View) {
if (selectionController?.onItemClick(item.id) != true) {
if ((activity as? MangaListActivity)?.showPreview(item) != true) {
router.openDetails(item)
val manga = item.toMangaWithOverride()
if ((activity as? MangaListActivity)?.showPreview(manga) != true) {
router.openDetails(manga)
}
}
}
override fun onItemLongClick(item: Manga, view: View): Boolean {
override fun onItemLongClick(item: MangaListModel, view: View): Boolean {
return selectionController?.onItemLongClick(view, item.id) == true
}
override fun onItemContextClick(item: Manga, view: View): Boolean {
override fun onItemContextClick(item: MangaListModel, view: View): Boolean {
return selectionController?.onItemContextClick(view, item.id) == true
}

View File

@@ -2,10 +2,11 @@ package org.koitharu.kotatsu.list.ui.adapter
import android.view.View
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
interface MangaDetailsClickListener : OnListItemClickListener<Manga> {
interface MangaDetailsClickListener : OnListItemClickListener<MangaListModel> {
fun onReadClick(manga: Manga, view: View)

View File

@@ -10,17 +10,17 @@ import org.koitharu.kotatsu.databinding.ItemMangaGridBinding
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROGRESS_CHANGED
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaGridModel
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
fun mangaGridItemAD(
sizeResolver: ItemSizeResolver,
clickListener: OnListItemClickListener<Manga>,
clickListener: OnListItemClickListener<MangaListModel>,
) = adapterDelegateViewBinding<MangaGridModel, ListModel, ItemMangaGridBinding>(
{ inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) },
) {
AdapterDelegateClickListenerAdapter(this, clickListener, MangaGridModel::manga).attach(itemView)
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
sizeResolver.attachToView(itemView, binding.textViewTitle, binding.progressView)
bind { payloads ->

View File

@@ -16,7 +16,8 @@ fun mangaListDetailedItemAD(
{ inflater, parent -> ItemMangaListDetailsBinding.inflate(inflater, parent, false) },
) {
AdapterDelegateClickListenerAdapter(this, clickListener, MangaDetailedListModel::manga).attach(itemView)
AdapterDelegateClickListenerAdapter(this, clickListener)
.attach(itemView)
bind { payloads ->
binding.textViewTitle.text = item.title

View File

@@ -1,6 +1,5 @@
package org.koitharu.kotatsu.list.ui.adapter
import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.isVisible
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
@@ -10,15 +9,15 @@ 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.MangaCompactListModel
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.list.ui.model.MangaListModel
fun mangaListItemAD(
clickListener: OnListItemClickListener<Manga>,
clickListener: OnListItemClickListener<MangaListModel>,
) = adapterDelegateViewBinding<MangaCompactListModel, ListModel, ItemMangaListBinding>(
{ inflater, parent -> ItemMangaListBinding.inflate(inflater, parent, false) },
) {
AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView)
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
bind {
itemView.setTooltipCompat(item.getSummary(context))

View File

@@ -1,12 +1,11 @@
package org.koitharu.kotatsu.list.ui.model
import org.koitharu.kotatsu.core.ui.model.MangaOverride
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 override: MangaOverride?,
val subtitle: String,
override val counter: Int,
) : MangaListModel()

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.list.ui.model
import org.koitharu.kotatsu.core.ui.model.MangaOverride
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.list.domain.ReadingProgress
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_ANYTHING_CHANGED
@@ -7,11 +8,9 @@ import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROG
import org.koitharu.kotatsu.parsers.model.Manga
data class MangaDetailedListModel(
override val id: Long,
override val title: String,
val subtitle: String?,
override val coverUrl: String?,
override val manga: Manga,
override val override: MangaOverride?,
val subtitle: String?,
override val counter: Int,
val progress: ReadingProgress?,
val isFavorite: Boolean,

View File

@@ -1,15 +1,14 @@
package org.koitharu.kotatsu.list.ui.model
import org.koitharu.kotatsu.core.ui.model.MangaOverride
import org.koitharu.kotatsu.list.domain.ReadingProgress
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_ANYTHING_CHANGED
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROGRESS_CHANGED
import org.koitharu.kotatsu.parsers.model.Manga
data class MangaGridModel(
override val id: Long,
override val title: String,
override val coverUrl: String?,
override val manga: Manga,
override val override: MangaOverride?,
override val counter: Int,
val progress: ReadingProgress?,
val isFavorite: Boolean,

View File

@@ -4,21 +4,33 @@ import android.content.Context
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.model.withOverride
import org.koitharu.kotatsu.core.ui.model.MangaOverride
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_ANYTHING_CHANGED
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
sealed class MangaListModel : ListModel {
abstract val id: Long
abstract val override: MangaOverride?
abstract val manga: Manga
abstract val title: String
abstract val coverUrl: String?
abstract val counter: Int
val id: Long
get() = manga.id
val title: String
get() = override?.title.ifNullOrEmpty { manga.title }
val coverUrl: String?
get() = override?.coverUrl.ifNullOrEmpty { manga.coverUrl }
val source: MangaSource
get() = manga.source
fun toMangaWithOverride() = manga.withOverride(override)
open fun getSummary(context: Context): CharSequence = buildSpannedString {
bold {
append(manga.title)

View File

@@ -5,7 +5,7 @@ import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.list.ui.MangaListFragment
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.picker.ui.PageImagePickActivity
@AndroidEntryPoint
@@ -17,8 +17,8 @@ class MangaPickerFragment : MangaListFragment() {
override fun onScrolledToEnd() = Unit
override fun onItemClick(item: Manga, view: View) {
(activity as PageImagePickActivity).onMangaPicked(item)
override fun onItemClick(item: MangaListModel, view: View) {
(activity as PageImagePickActivity).onMangaPicked(item.manga)
}
override fun onResume() {
@@ -26,7 +26,7 @@ class MangaPickerFragment : MangaListFragment() {
activity?.setTitle(R.string.pick_manga_page)
}
override fun onItemLongClick(item: Manga, view: View): Boolean = false
override fun onItemLongClick(item: MangaListModel, view: View): Boolean = false
override fun onItemContextClick(item: Manga, view: View): Boolean = false
override fun onItemContextClick(item: MangaListModel, view: View): Boolean = false
}

View File

@@ -30,6 +30,7 @@ import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
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.MangaListModel
import org.koitharu.kotatsu.list.ui.size.DynamicItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
@@ -115,17 +116,17 @@ class SearchActivity :
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: Manga, view: View) {
override fun onItemClick(item: MangaListModel, view: View) {
if (!selectionController.onItemClick(item.id)) {
router.openDetails(item)
router.openDetails(item.toMangaWithOverride())
}
}
override fun onItemLongClick(item: Manga, view: View): Boolean {
override fun onItemLongClick(item: MangaListModel, view: View): Boolean {
return selectionController.onItemLongClick(view, item.id)
}
override fun onItemContextClick(item: Manga, view: View): Boolean {
override fun onItemContextClick(item: MangaListModel, view: View): Boolean {
return selectionController.onItemContextClick(view, item.id)
}

View File

@@ -17,8 +17,8 @@ import org.koitharu.kotatsu.databinding.ItemListGroupBinding
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
import org.koitharu.kotatsu.list.ui.adapter.mangaGridItemAD
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.search.ui.multi.SearchResultsListModel
@SuppressLint("NotifyDataSetChanged")
@@ -26,7 +26,7 @@ fun searchResultsAD(
sharedPool: RecycledViewPool,
sizeResolver: ItemSizeResolver,
selectionDecoration: MangaSelectionDecoration,
listener: OnListItemClickListener<Manga>,
listener: OnListItemClickListener<MangaListModel>,
itemClickListener: OnListItemClickListener<SearchResultsListModel>,
) = adapterDelegateViewBinding<SearchResultsListModel, ListModel, ItemListGroupBinding>(
{ layoutInflater, parent -> ItemListGroupBinding.inflate(layoutInflater, parent, false) },

View File

@@ -31,6 +31,7 @@ import org.koitharu.kotatsu.list.domain.ListFilterOption
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.MangaListModel
import org.koitharu.kotatsu.list.ui.size.StaticItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
@@ -63,7 +64,7 @@ class FeedFragment :
val sizeResolver = StaticItemSizeResolver(resources.getDimensionPixelSize(R.dimen.smaller_grid_width))
val feedAdapter = FeedAdapter(this, sizeResolver) { item, v ->
viewModel.onItemClick(item)
onItemClick(item.manga, v)
router.openDetails(item.toMangaWithOverride())
}
with(binding.recyclerView) {
val paddingVertical = resources.getDimensionPixelSize(R.dimen.list_spacing_normal)
@@ -126,8 +127,8 @@ class FeedFragment :
viewModel.requestMoreItems()
}
override fun onItemClick(item: Manga, view: View) {
router.openDetails(item)
override fun onItemClick(item: MangaListModel, view: View) {
router.openDetails(item.toMangaWithOverride())
}
override fun onReadClick(manga: Manga, view: View) = Unit

View File

@@ -38,7 +38,6 @@ import org.koitharu.kotatsu.tracker.domain.UpdatesListQuickFilter
import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem
import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem
import org.koitharu.kotatsu.tracker.ui.feed.model.UpdatedMangaHeader
import org.koitharu.kotatsu.tracker.ui.feed.model.toFeedItem
import org.koitharu.kotatsu.tracker.work.TrackWorker
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
@@ -132,7 +131,7 @@ class FeedViewModel @Inject constructor(
}
}
private fun List<TrackingLogItem>.mapListTo(destination: MutableList<ListModel>) {
private suspend fun List<TrackingLogItem>.mapListTo(destination: MutableList<ListModel>) {
var prevDate: DateTimeAgo? = null
for (item in this) {
val date = calculateTimeAgo(item.createdAt)
@@ -144,7 +143,7 @@ class FeedViewModel @Inject constructor(
}
}
prevDate = date
destination += item.toFeedItem()
destination += mangaListMapper.toFeedItem(item)
}
}

View File

@@ -10,13 +10,13 @@ import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.mangaGridItemAD
import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaListModel
import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.tracker.ui.feed.model.UpdatedMangaHeader
fun updatedMangaAD(
sizeResolver: ItemSizeResolver,
listener: OnListItemClickListener<Manga>,
listener: OnListItemClickListener<MangaListModel>,
headerClickListener: ListHeaderClickListener,
) = adapterDelegateViewBinding<UpdatedMangaHeader, ListModel, ItemListGroupBinding>(
{ layoutInflater, parent -> ItemListGroupBinding.inflate(layoutInflater, parent, false) },

View File

@@ -1,18 +1,28 @@
package org.koitharu.kotatsu.tracker.ui.feed.model
import org.koitharu.kotatsu.core.model.withOverride
import org.koitharu.kotatsu.core.ui.model.MangaOverride
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
data class FeedItem(
val id: Long,
val imageUrl: String?,
val title: String,
private val override: MangaOverride?,
val manga: Manga,
val count: Int,
val isNew: Boolean,
) : ListModel {
val imageUrl: String?
get() = override?.coverUrl.ifNullOrEmpty { manga.coverUrl }
val title: String
get() = override?.title.ifNullOrEmpty { manga.title }
fun toMangaWithOverride() = manga.withOverride(override)
override fun areItemsTheSame(other: ListModel): Boolean {
return other is FeedItem && other.id == id
}

View File

@@ -1,12 +0,0 @@
package org.koitharu.kotatsu.tracker.ui.feed.model
import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem
fun TrackingLogItem.toFeedItem() = FeedItem(
id = id,
imageUrl = manga.coverUrl,
title = manga.title,
count = chapters.size,
manga = manga,
isNew = isNew,
)