diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt index 1d0b2bc10..879e708bb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt @@ -16,9 +16,15 @@ interface TrackLogsDao { @Query("SELECT * FROM track_logs ORDER BY created_at DESC LIMIT :limit OFFSET 0") fun observeAll(limit: Int): Flow> + @Query("SELECT COUNT(*) FROM track_logs WHERE unread = 1") + fun observeUnreadCount(): Flow + @Query("DELETE FROM track_logs") suspend fun clear() + @Query("UPDATE track_logs SET unread = 0 WHERE id = :id") + suspend fun markAsRead(id: Long) + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(entity: TrackLogEntity): Long diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration19To20.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration19To20.kt index 0bd5d3c8e..f3b39e5d8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration19To20.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration19To20.kt @@ -12,5 +12,7 @@ class Migration19To20 : Migration(19, 20) { db.execSQL("CREATE TABLE tracks (`manga_id` INTEGER NOT NULL, `last_chapter_id` INTEGER NOT NULL, `chapters_new` INTEGER NOT NULL, `last_check_time` INTEGER NOT NULL, `last_chapter_date` INTEGER NOT NULL, `last_result` INTEGER NOT NULL, PRIMARY KEY(`manga_id`), FOREIGN KEY(`manga_id`) REFERENCES `manga`(`manga_id`) ON UPDATE NO ACTION ON DELETE CASCADE )") db.execSQL("INSERT INTO tracks SELECT manga_id, last_chapter_id, chapters_new, last_check AS last_check_time, 0 AS last_chapter_date, 0 AS last_result FROM tracks_bk") db.execSQL("DROP TABLE tracks_bk") + + db.execSQL("ALTER TABLE track_logs ADD COLUMN `unread` INTEGER NOT NULL DEFAULT 0") } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/AcraCoroutineErrorHandler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/AcraCoroutineErrorHandler.kt new file mode 100644 index 000000000..23502844c --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/AcraCoroutineErrorHandler.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.core.util + +import kotlinx.coroutines.CoroutineExceptionHandler +import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug +import org.koitharu.kotatsu.core.util.ext.report +import kotlin.coroutines.AbstractCoroutineContextElement +import kotlin.coroutines.CoroutineContext + +class AcraCoroutineErrorHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler), + CoroutineExceptionHandler { + + override fun handleException(context: CoroutineContext, exception: Throwable) { + exception.printStackTraceDebug() + exception.report() + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt index 3eed0b6a8..c2ccef138 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.core.util.ext import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleDestroyedException import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleObserver @@ -10,17 +9,20 @@ import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.lifecycleScope import dagger.hilt.android.lifecycle.RetainedLifecycle import kotlinx.coroutines.CancellableContinuation +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.plus import kotlinx.coroutines.suspendCancellableCoroutine +import org.koitharu.kotatsu.core.util.AcraCoroutineErrorHandler import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException -val processLifecycleScope: LifecycleCoroutineScope - inline get() = ProcessLifecycleOwner.get().lifecycleScope +val processLifecycleScope: CoroutineScope + get() = ProcessLifecycleOwner.get().lifecycleScope + AcraCoroutineErrorHandler() val RetainedLifecycle.lifecycleScope: RetainedLifecycleCoroutineScope inline get() = RetainedLifecycleCoroutineScope(this) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt index b79693a55..c38344f4d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt @@ -118,7 +118,7 @@ class ExploreViewModel @Inject constructor( sourcesRepository.observeNewSources(), ) { content, suggestions, grid, randomLoading, newSources -> buildList(content, suggestions, grid, randomLoading, newSources) - } + }.withErrorHandling() private fun buildList( sources: List, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt index 4b680f8a8..3df13093a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt @@ -40,7 +40,8 @@ class FavouritesCategoriesViewModel @Inject constructor( settings.observeAsFlow(AppSettings.KEY_ALL_FAVOURITES_VISIBLE) { isAllFavouritesVisible }, ) { cats, all, showAll -> cats.toUiList(all, showAll) - }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) + }.withErrorHandling() + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) fun deleteCategories(ids: Set) { launchJob(Dispatchers.Default) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index c2e3a277e..a8f8e04b5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -56,6 +56,7 @@ class FavouritesListViewModel @Inject constructor( } } else { repository.observeCategory(categoryId) + .withErrorHandling() .map { it?.order } }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt index 779c8fc93..c3716f9cf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -277,7 +277,6 @@ class MainActivity : BaseActivity(), AppBarOwner, BottomNav private fun onFeedCounterChanged(counter: Int) { navigationDelegate.setCounter(NavItem.FEED, counter) - navigationDelegate.setCounter(NavItem.UPDATED, counter) } private fun onIncognitoModeChanged(isIncognito: Boolean) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt index 505f8cc07..aaaf655b3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt @@ -32,15 +32,18 @@ class MainViewModel @Inject constructor( val onOpenReader = MutableEventFlow() val onFirstStart = MutableEventFlow() - val isResumeEnabled = readingResumeEnabledUseCase().stateIn( - scope = viewModelScope + Dispatchers.Default, - started = SharingStarted.WhileSubscribed(5000), - initialValue = false, - ) + val isResumeEnabled = readingResumeEnabledUseCase() + .withErrorHandling() + .stateIn( + scope = viewModelScope + Dispatchers.Default, + started = SharingStarted.WhileSubscribed(5000), + initialValue = false, + ) val appUpdate = appUpdateRepository.observeAvailableUpdate() - val feedCounter = trackingRepository.observeUpdatedMangaCount() + val feedCounter = trackingRepository.observeUnreadUpdatesCount() + .withErrorHandling() .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, 0) init { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt index 8596fbd74..e4912614b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt @@ -106,7 +106,7 @@ class SearchSuggestionViewModel @Inject constructor( }.distinctUntilChanged() .onEach { suggestion.value = it - }.launchIn(viewModelScope + Dispatchers.Default) + }.withErrorHandling().launchIn(viewModelScope + Dispatchers.Default) } private suspend fun buildSearchSuggestion( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsViewModel.kt index b997b8236..adcb88148 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsViewModel.kt @@ -18,5 +18,6 @@ class RootSettingsViewModel @Inject constructor( val totalSourcesCount = sourcesRepository.allMangaSources.size val enabledSourcesCount = sourcesRepository.observeEnabledSourcesCount() + .withErrorHandling() .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt index 2d8f52c3c..164389541 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesSettingsViewModel.kt @@ -16,8 +16,10 @@ class SourcesSettingsViewModel @Inject constructor( ) : BaseViewModel() { val enabledSourcesCount = sourcesRepository.observeEnabledSourcesCount() + .withErrorHandling() .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1) val availableSourcesCount = sourcesRepository.observeAvailableSourcesCount() + .withErrorHandling() .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, -1) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt index 2f84a7b61..5af404b93 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt @@ -5,26 +5,13 @@ import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem import java.time.Instant -fun TrackLogWithManga.toTrackingLogItem(counters: MutableMap): TrackingLogItem { +fun TrackLogWithManga.toTrackingLogItem(): TrackingLogItem { val chaptersList = trackLog.chapters.split('\n').filterNot { x -> x.isEmpty() } return TrackingLogItem( id = trackLog.id, chapters = chaptersList, manga = manga.toManga(tags.toMangaTags()), createdAt = Instant.ofEpochMilli(trackLog.createdAt), - isNew = counters.decrement(trackLog.mangaId, chaptersList.size), + isNew = trackLog.isUnread, ) } - -private fun MutableMap.decrement(key: Long, count: Int): Boolean = synchronized(this) { - val counter = get(key) - if (counter == null || counter <= 0) { - return false - } - if (counter < count) { - remove(key) - } else { - put(key, counter - count) - } - return true -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt index 5f2dd4896..7d3acb077 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt @@ -23,4 +23,5 @@ class TrackLogEntity( @ColumnInfo(name = "manga_id", index = true) val mangaId: Long, @ColumnInfo(name = "chapters") val chapters: String, @ColumnInfo(name = "created_at") val createdAt: Long, + @ColumnInfo(name = "unread") val isUnread: Boolean, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt index 63e8abcf0..059165b46 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt @@ -4,7 +4,6 @@ import androidx.annotation.VisibleForTesting import androidx.room.withTransaction import dagger.Reusable import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map @@ -55,11 +54,16 @@ class TrackingRepository @Inject constructor( return db.getTracksDao().observeNewChapters(mangaId).map { it ?: 0 } } + @Deprecated("") fun observeUpdatedMangaCount(): Flow { return db.getTracksDao().observeNewChapters().map { list -> list.count { it > 0 } } .onStart { gcIfNotCalled() } } + fun observeUnreadUpdatesCount(): Flow { + return db.getTrackLogsDao().observeUnreadCount() + } + fun observeUpdatedManga(limit: Int = 0): Flow> { return if (limit == 0) { db.getTracksDao().observeUpdatedManga() @@ -112,13 +116,8 @@ class TrackingRepository @Inject constructor( fun observeTrackingLog(limit: Flow): Flow> { return limit.flatMapLatest { limitValue -> - combine( - db.getTracksDao().observeNewChaptersMap(), - db.getTrackLogsDao().observeAll(limitValue), - ) { counters, entities -> - val countersMap = counters.toMutableMap() - entities.map { x -> x.toTrackingLogItem(countersMap) } - } + db.getTrackLogsDao().observeAll(limitValue) + .mapItems { it.toTrackingLogItem() } }.onStart { gcIfNotCalled() } @@ -130,6 +129,8 @@ class TrackingRepository @Inject constructor( suspend fun clearCounters() = db.getTracksDao().clearCounters() + suspend fun markAsRead(trackLogId: Long) = db.getTrackLogsDao().markAsRead(trackLogId) + suspend fun gc() = db.withTransaction { db.getTracksDao().gc() db.getTrackLogsDao().run { @@ -148,6 +149,7 @@ class TrackingRepository @Inject constructor( mangaId = updates.manga.id, chapters = updates.newChapters.joinToString("\n") { x -> x.name }, createdAt = System.currentTimeMillis(), + isUnread = true, ) db.getTrackLogsDao().insert(logEntity) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt index 474087f86..6d16293ff 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt @@ -57,7 +57,10 @@ class FeedFragment : override fun onViewBindingCreated(binding: FragmentFeedBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) val sizeResolver = StaticItemSizeResolver(resources.getDimensionPixelSize(R.dimen.smaller_grid_width)) - feedAdapter = FeedAdapter(coil, viewLifecycleOwner, this, sizeResolver) + feedAdapter = FeedAdapter(coil, viewLifecycleOwner, this, sizeResolver) { item, v -> + viewModel.onItemClick(item) + onItemClick(item.manga, v) + } with(binding.recyclerView) { adapter = feedAdapter setHasFixedSize(true) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt index 5d4687f91..511ef1aae 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.tracker.ui.feed import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -27,6 +28,7 @@ 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 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 @@ -108,6 +110,12 @@ class FeedViewModel @Inject constructor( settings.isFeedHeaderVisible = value } + fun onItemClick(item: FeedItem) { + launchJob(Dispatchers.Default, CoroutineStart.ATOMIC) { + repository.markAsRead(item.id) + } + } + private fun List.mapListTo(destination: MutableList) { var prevDate: DateTimeAgo? = null for (item in this) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt index 2e65e20fc..15cdeb9dd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import org.koitharu.kotatsu.core.ui.BaseListAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.MangaListListener @@ -15,16 +16,18 @@ import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.size.ItemSizeResolver +import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem class FeedAdapter( coil: ImageLoader, lifecycleOwner: LifecycleOwner, listener: MangaListListener, sizeResolver: ItemSizeResolver, + feedClickListener: OnListItemClickListener, ) : BaseListAdapter(), FastScroller.SectionIndexer { init { - addDelegate(ListItemType.FEED, feedItemAD(coil, lifecycleOwner, listener)) + addDelegate(ListItemType.FEED, feedItemAD(coil, lifecycleOwner, feedClickListener)) addDelegate( ListItemType.MANGA_NESTED_GROUP, updatedMangaAD( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt index c12726e74..2eaab8816 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt @@ -12,20 +12,19 @@ import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemFeedBinding import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem fun feedItemAD( coil: ImageLoader, lifecycleOwner: LifecycleOwner, - clickListener: OnListItemClickListener, + clickListener: OnListItemClickListener, ) = adapterDelegateViewBinding( { inflater, parent -> ItemFeedBinding.inflate(inflater, parent, false) }, ) { val indicatorNew = ContextCompat.getDrawable(context, R.drawable.ic_new) itemView.setOnClickListener { - clickListener.onItemClick(item.manga, it) + clickListener.onItemClick(item, it) } bind { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt index 7cc085d4b..bf9510a51 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt @@ -1,5 +1,6 @@ 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.parsers.model.Manga @@ -11,7 +12,14 @@ data class FeedItem( val count: Int, val isNew: Boolean, ) : ListModel { + override fun areItemsTheSame(other: ListModel): Boolean { return other is FeedItem && other.id == id } + + override fun getChangePayload(previousState: ListModel): Any? = when { + previousState !is FeedItem -> null + isNew != previousState.isNew -> ListModelDiffCallback.PAYLOAD_ANYTHING_CHANGED + else -> super.getChangePayload(previousState) + } }