diff --git a/app/build.gradle b/app/build.gradle index 73554c773..4522ba6d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,19 +84,19 @@ afterEvaluate { } } dependencies { - implementation('com.github.KotatsuApp:kotatsu-parsers:85bfe42ddf') { + implementation('com.github.KotatsuApp:kotatsu-parsers:e2308214a7') { exclude group: 'org.json', module: 'json' } implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.activity:activity-ktx:1.5.0' - implementation 'androidx.fragment:fragment-ktx:1.5.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.0' - implementation 'androidx.lifecycle:lifecycle-service:2.5.0' - implementation 'androidx.lifecycle:lifecycle-process:2.5.0' + implementation 'androidx.activity:activity-ktx:1.5.1' + implementation 'androidx.fragment:fragment-ktx:1.5.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-service:2.5.1' + implementation 'androidx.lifecycle:lifecycle-process:2.5.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' @@ -106,11 +106,11 @@ dependencies { implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha04' implementation 'com.google.android.material:material:1.7.0-alpha03' //noinspection LifecycleAnnotationProcessorWithJava8 - kapt 'androidx.lifecycle:lifecycle-compiler:2.5.0' + kapt 'androidx.lifecycle:lifecycle-compiler:2.5.1' - implementation 'androidx.room:room-runtime:2.4.2' - implementation 'androidx.room:room-ktx:2.4.2' - kapt 'androidx.room:room-compiler:2.4.2' + implementation 'androidx.room:room-runtime:2.4.3' + implementation 'androidx.room:room-ktx:2.4.3' + kapt 'androidx.room:room-compiler:2.4.3' implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3' @@ -145,7 +145,7 @@ dependencies { androidTestImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4' - androidTestImplementation 'androidx.room:room-testing:2.4.2' + androidTestImplementation 'androidx.room:room-testing:2.4.3' androidTestImplementation 'com.squareup.moshi:moshi-kotlin:1.13.0' androidTestImplementation 'com.google.dagger:hilt-android-testing:2.42' diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt index 5d601d67c..2d18292cc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt @@ -10,6 +10,7 @@ import android.widget.Checkable import androidx.annotation.AttrRes import androidx.appcompat.widget.AppCompatImageView import androidx.core.os.ParcelCompat +import androidx.customview.view.AbsSavedState class CheckableImageView @JvmOverloads constructor( context: Context, @@ -73,7 +74,7 @@ class CheckableImageView @JvmOverloads constructor( fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean) } - private class SavedState : BaseSavedState { + private class SavedState : AbsSavedState { val isChecked: Boolean @@ -81,7 +82,7 @@ class CheckableImageView @JvmOverloads constructor( isChecked = checked } - constructor(source: Parcel) : super(source) { + constructor(source: Parcel, classLoader: ClassLoader?) : super(source, classLoader) { isChecked = ParcelCompat.readBoolean(source) } @@ -91,9 +92,10 @@ class CheckableImageView @JvmOverloads constructor( } companion object { + @Suppress("unused") @JvmField val CREATOR: Creator = object : Creator { - override fun createFromParcel(`in`: Parcel) = SavedState(`in`) + override fun createFromParcel(`in`: Parcel) = SavedState(`in`, SavedState::class.java.classLoader) override fun newArray(size: Int): Array = arrayOfNulls(size) } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt index ed5594c42..3097f0ac3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt @@ -1,6 +1,34 @@ package org.koitharu.kotatsu.core.model +import androidx.core.os.LocaleListCompat import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.toTitleCase +import org.koitharu.kotatsu.utils.ext.iterator -fun Collection.ids() = mapToSet { it.id } \ No newline at end of file +fun Collection.ids() = mapToSet { it.id } + +fun Manga.getPreferredBranch(history: MangaHistory?): String? { + val ch = chapters + if (ch.isNullOrEmpty()) { + return null + } + if (history != null) { + val currentChapter = ch.find { it.id == history.chapterId } + if (currentChapter != null) { + return currentChapter.branch + } + } + val groups = ch.groupBy { it.branch } + for (locale in LocaleListCompat.getAdjustedDefault()) { + var language = locale.getDisplayLanguage(locale).toTitleCase(locale) + if (groups.containsKey(language)) { + return language + } + language = locale.getDisplayName(locale).toTitleCase(locale) + if (groups.containsKey(language)) { + return language + } + } + return groups.maxByOrNull { it.value.size }?.key +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index ff5924c7b..6d8a4d0f3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -29,6 +29,7 @@ import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.databinding.FragmentDetailsBinding +import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingInfoBottomSheet import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.image.ui.ImageActivity @@ -75,6 +76,7 @@ class DetailsFragment : viewModel.bookmarks.observe(viewLifecycleOwner, ::onBookmarksChanged) viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged) viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged) + viewModel.chapters.observe(viewLifecycleOwner, ::onChaptersChanged) } override fun onItemClick(item: Bookmark, view: View) { @@ -111,18 +113,6 @@ class DetailsFragment : ratingBar.isVisible = false } - // Info containers - val chapters = manga.chapters - if (chapters.isNullOrEmpty()) { - infoLayout.textViewChapters.isVisible = false - } else { - infoLayout.textViewChapters.isVisible = true - infoLayout.textViewChapters.text = resources.getQuantityString( - R.plurals.chapters, - chapters.size, - chapters.size, - ) - } when (manga.state) { MangaState.FINISHED -> { infoLayout.textViewState.apply { @@ -163,6 +153,20 @@ class DetailsFragment : } } + private fun onChaptersChanged(chapters: List?) { + val infoLayout = binding.infoLayout + if (chapters.isNullOrEmpty()) { + infoLayout.textViewChapters.isVisible = false + } else { + infoLayout.textViewChapters.isVisible = true + infoLayout.textViewChapters.text = resources.getQuantityString( + R.plurals.chapters, + chapters.size, + chapters.size, + ) + } + } + private fun onDescriptionChanged(description: CharSequence?) { if (description.isNullOrBlank()) { binding.textViewDescription.setText(R.string.no_description) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt index 4fd58b55c..0f7a320a3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt @@ -1,11 +1,11 @@ package org.koitharu.kotatsu.details.ui -import androidx.core.os.LocaleListCompat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.core.model.MangaHistory +import org.koitharu.kotatsu.core.model.getPreferredBranch import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.details.ui.model.ChapterListItem @@ -16,9 +16,6 @@ import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.parsers.util.toTitleCase -import org.koitharu.kotatsu.utils.ext.iterator import org.koitharu.kotatsu.utils.ext.printStackTraceDebug class MangaDetailsDelegate( @@ -46,12 +43,7 @@ class MangaDetailsDelegate( manga = mangaRepositoryFactory.create(manga.source).getDetails(manga) // find default branch val hist = historyRepository.getOne(manga) - selectedBranch.value = if (hist != null) { - val currentChapter = manga.chapters?.find { it.id == hist.chapterId } - if (currentChapter != null) currentChapter.branch else predictBranch(manga.chapters) - } else { - predictBranch(manga.chapters) - } + selectedBranch.value = manga.getPreferredBranch(hist) mangaData.value = manga relatedManga.value = runCatching { if (manga.source == MangaSource.LOCAL) { @@ -92,7 +84,7 @@ class MangaDetailsDelegate( val dateFormat = settings.getDateFormat() val currentIndex = chapters.indexOfFirst { it.id == currentId } val firstNewIndex = chapters.size - newCount - val downloadedIds = downloadedChapters?.mapToSet { it.id } + val downloadedIds = downloadedChapters?.mapTo(HashSet(downloadedChapters.size)) { it.id } for (i in chapters.indices) { val chapter = chapters[i] if (chapter.branch != branch) { @@ -107,6 +99,9 @@ class MangaDetailsDelegate( dateFormat = dateFormat, ) } + if (result.size < chapters.size / 2) { + result.trimToSize() + } return result } @@ -162,24 +157,9 @@ class MangaDetailsDelegate( } result.sortBy { it.chapter.number } } + if (result.size < sourceChapters.size / 2) { + result.trimToSize() + } return result } - - private fun predictBranch(chapters: List?): String? { - if (chapters.isNullOrEmpty()) { - return null - } - val groups = chapters.groupBy { it.branch } - for (locale in LocaleListCompat.getAdjustedDefault()) { - var language = locale.getDisplayLanguage(locale).toTitleCase(locale) - if (groups.containsKey(language)) { - return language - } - language = locale.getDisplayName(locale).toTitleCase(locale) - if (groups.containsKey(language)) { - return language - } - } - return groups.maxByOrNull { it.value.size }?.key - } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt index 2d5b90840..7de226908 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt @@ -1,13 +1,24 @@ package org.koitharu.kotatsu.details.ui.model +import java.text.DateFormat import org.koitharu.kotatsu.parsers.model.MangaChapter class ChapterListItem( val chapter: MangaChapter, val flags: Int, - val uploadDate: String?, + private val uploadDateMs: Long, + private val dateFormat: DateFormat, ) { + var uploadDate: String? = null + private set + get() { + if (field != null) return field + if (uploadDateMs == 0L) return null + field = dateFormat.format(uploadDateMs) + return field + } + val status: Int get() = flags and MASK_STATUS @@ -32,7 +43,8 @@ class ChapterListItem( if (chapter != other.chapter) return false if (flags != other.flags) return false - if (uploadDate != other.uploadDate) return false + if (uploadDateMs != other.uploadDateMs) return false + if (dateFormat != other.dateFormat) return false return true } @@ -40,7 +52,8 @@ class ChapterListItem( override fun hashCode(): Int { var result = chapter.hashCode() result = 31 * result + flags - result = 31 * result + (uploadDate?.hashCode() ?: 0) + result = 31 * result + uploadDateMs.hashCode() + result = 31 * result + dateFormat.hashCode() return result } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt index 22d272346..e15669f94 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt @@ -1,12 +1,12 @@ package org.koitharu.kotatsu.details.ui.model +import java.text.DateFormat import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_CURRENT import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_DOWNLOADED import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_MISSING import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_NEW import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_UNREAD import org.koitharu.kotatsu.parsers.model.MangaChapter -import java.text.DateFormat fun MangaChapter.toListItem( isCurrent: Boolean, @@ -25,6 +25,7 @@ fun MangaChapter.toListItem( return ChapterListItem( chapter = this, flags = flags, - uploadDate = if (uploadDate != 0L) dateFormat.format(uploadDate) else null + uploadDateMs = uploadDate, + dateFormat = dateFormat, ) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt index 0933fe1d0..b2a818caa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt @@ -5,8 +5,8 @@ import android.content.res.TypedArray import android.os.Parcel import android.os.Parcelable import android.util.AttributeSet -import android.view.View import androidx.core.content.withStyledAttributes +import androidx.customview.view.AbsSavedState import androidx.preference.Preference import androidx.preference.PreferenceViewHolder import com.google.android.material.slider.Slider @@ -40,11 +40,11 @@ class SliderPreference @JvmOverloads constructor( attrs, R.styleable.SliderPreference, defStyleAttr, - defStyleRes + defStyleRes, ) { valueFrom = getFloat( R.styleable.SliderPreference_android_valueFrom, - valueFrom.toFloat() + valueFrom.toFloat(), ).toInt() valueTo = getFloat(R.styleable.SliderPreference_android_valueTo, valueTo.toFloat()).toInt() @@ -117,7 +117,7 @@ class SliderPreference @JvmOverloads constructor( } } - private class SavedState : View.BaseSavedState { + private class SavedState : AbsSavedState { val valueFrom: Int val valueTo: Int @@ -134,7 +134,7 @@ class SliderPreference @JvmOverloads constructor( this.currentValue = currentValue } - constructor(source: Parcel) : super(source) { + constructor(source: Parcel, classLoader: ClassLoader?) : super(source, classLoader) { valueFrom = source.readInt() valueTo = source.readInt() currentValue = source.readInt() @@ -148,12 +148,13 @@ class SliderPreference @JvmOverloads constructor( } companion object { + @Suppress("unused") @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(`in`: Parcel) = SavedState(`in`) + override fun createFromParcel(`in`: Parcel) = SavedState(`in`, SavedState::class.java.classLoader) override fun newArray(size: Int): Array = arrayOfNulls(size) } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt index bc66e7789..31df0a6be 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt @@ -2,8 +2,10 @@ package org.koitharu.kotatsu.tracker.domain import androidx.annotation.VisibleForTesting import javax.inject.Inject +import org.koitharu.kotatsu.core.model.getPreferredBranch import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.domain.model.MangaTracking import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates @@ -13,6 +15,7 @@ import org.koitharu.kotatsu.tracker.work.TrackingItem class Tracker @Inject constructor( private val settings: AppSettings, private val repository: TrackingRepository, + private val historyRepository: HistoryRepository, private val channels: TrackerNotificationChannels, private val mangaRepositoryFactory: MangaRepository.Factory, ) { @@ -70,7 +73,7 @@ class Tracker @Inject constructor( suspend fun fetchUpdates(track: MangaTracking, commit: Boolean): MangaUpdates { val manga = mangaRepositoryFactory.create(track.manga.source).getDetails(track.manga) - val updates = compare(track, manga) + val updates = compare(track, manga, getBranch(manga)) if (commit) { repository.saveUpdates(updates) } @@ -80,7 +83,7 @@ class Tracker @Inject constructor( @VisibleForTesting suspend fun checkUpdates(manga: Manga, commit: Boolean): MangaUpdates { val track = repository.getTrack(manga) - val updates = compare(track, manga) + val updates = compare(track, manga, getBranch(manga)) if (commit) { repository.saveUpdates(updates) } @@ -92,15 +95,20 @@ class Tracker @Inject constructor( repository.deleteTrack(mangaId) } + private suspend fun getBranch(manga: Manga): String? { + val history = historyRepository.getOne(manga) + return manga.getPreferredBranch(history) + } + /** * The main functionality of tracker: check new chapters in [manga] comparing to the [track] */ - private fun compare(track: MangaTracking, manga: Manga): MangaUpdates { + private fun compare(track: MangaTracking, manga: Manga, branch: String?): MangaUpdates { if (track.isEmpty()) { // first check or manga was empty on last check return MangaUpdates(manga, emptyList(), isValid = false) } - val chapters = requireNotNull(manga.chapters) + val chapters = requireNotNull(manga.getChapters(branch)) val newChapters = chapters.takeLastWhile { x -> x.id != track.lastChapterId } return when { newChapters.isEmpty() -> { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt index 5e5efa840..de32ff903 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt @@ -17,7 +17,8 @@ fun Throwable.getDisplayMessage(resources: Resources): String = when (this) { is AuthRequiredException -> resources.getString(R.string.auth_required) is CloudFlareProtectedException -> resources.getString(R.string.captcha_required) is ActivityNotFoundException, - is UnsupportedOperationException, -> resources.getString(R.string.operation_not_supported) + is UnsupportedOperationException, + -> resources.getString(R.string.operation_not_supported) is UnsupportedFileException -> resources.getString(R.string.text_file_not_supported) is FileNotFoundException -> resources.getString(R.string.file_not_found) is EmptyHistoryException -> resources.getString(R.string.history_is_empty) @@ -40,5 +41,6 @@ fun Throwable.isReportable(): Boolean { } fun Throwable.report(message: String?) { - CaughtException(this, message).sendWithAcra() + val exception = CaughtException(this, message) + exception.sendWithAcra() } diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt index 86a1d91e1..88487c636 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt @@ -14,17 +14,18 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.replaceWith import org.koitharu.kotatsu.utils.ext.requireBitmap class RecentListFactory( private val context: Context, private val historyRepository: HistoryRepository, - private val coil: ImageLoader + private val coil: ImageLoader, ) : RemoteViewsService.RemoteViewsFactory { private val dataSet = ArrayList() private val transformation = RoundedCornersTransformation( - context.resources.getDimension(R.dimen.appwidget_corner_radius_inner) + context.resources.getDimension(R.dimen.appwidget_corner_radius_inner), ) private val coverSize = Size( context.resources.getDimensionPixelSize(R.dimen.widget_cover_width), @@ -38,9 +39,8 @@ class RecentListFactory( override fun getItemId(position: Int) = dataSet[position].id override fun onDataSetChanged() { - dataSet.clear() val data = runBlocking { historyRepository.getList(0, 10) } - dataSet.addAll(data) + dataSet.replaceWith(data) } override fun hasStableIds() = true @@ -54,7 +54,7 @@ class RecentListFactory( .data(item.coverUrl) .size(coverSize) .transformations(transformation) - .build() + .build(), ).requireBitmap() }.onSuccess { cover -> views.setImageViewBitmap(R.id.imageView_cover, cover) @@ -72,4 +72,4 @@ class RecentListFactory( override fun getViewTypeCount() = 1 override fun onDestroy() = Unit -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt index 42c3dd832..6572418d3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt @@ -15,6 +15,7 @@ import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.replaceWith import org.koitharu.kotatsu.utils.ext.requireBitmap class ShelfListFactory( @@ -27,7 +28,7 @@ class ShelfListFactory( private val dataSet = ArrayList() private val config = AppWidgetConfig(context, widgetId) private val transformation = RoundedCornersTransformation( - context.resources.getDimension(R.dimen.appwidget_corner_radius_inner) + context.resources.getDimension(R.dimen.appwidget_corner_radius_inner), ) private val coverSize = Size( context.resources.getDimensionPixelSize(R.dimen.widget_cover_width), @@ -41,7 +42,6 @@ class ShelfListFactory( override fun getItemId(position: Int) = dataSet[position].id override fun onDataSetChanged() { - dataSet.clear() val data = runBlocking { val category = config.categoryId if (category == 0L) { @@ -50,7 +50,7 @@ class ShelfListFactory( favouritesRepository.getManga(category) } } - dataSet.addAll(data) + dataSet.replaceWith(data) } override fun hasStableIds() = true @@ -65,7 +65,7 @@ class ShelfListFactory( .data(item.coverUrl) .size(coverSize) .transformations(transformation) - .build() + .build(), ).requireBitmap() }.onSuccess { cover -> views.setImageViewBitmap(R.id.imageView_cover, cover)