Cache chapters list (close #812)

This commit is contained in:
Koitharu
2024-12-20 11:21:49 +02:00
parent 3f66c142b8
commit 22e2411c77
25 changed files with 212 additions and 54 deletions

View File

@@ -29,8 +29,9 @@ class AutoFixUseCase @Inject constructor(
) {
suspend operator fun invoke(mangaId: Long): Pair<Manga, Manga?> {
val seed = checkNotNull(mangaDataRepository.findMangaById(mangaId)) { "Manga $mangaId not found" }
.getDetailsSafe()
val seed = checkNotNull(
mangaDataRepository.findMangaById(mangaId, withChapters = true),
) { "Manga $mangaId not found" }.getDetailsSafe()
if (seed.isHealthy()) {
return seed to null // no fix required
}

View File

@@ -12,11 +12,13 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import org.koitharu.kotatsu.bookmarks.data.BookmarkEntity
import org.koitharu.kotatsu.bookmarks.data.BookmarksDao
import org.koitharu.kotatsu.core.db.dao.ChaptersDao
import org.koitharu.kotatsu.core.db.dao.MangaDao
import org.koitharu.kotatsu.core.db.dao.MangaSourcesDao
import org.koitharu.kotatsu.core.db.dao.PreferencesDao
import org.koitharu.kotatsu.core.db.dao.TagsDao
import org.koitharu.kotatsu.core.db.dao.TrackLogsDao
import org.koitharu.kotatsu.core.db.entity.ChapterEntity
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
import org.koitharu.kotatsu.core.db.entity.MangaSourceEntity
@@ -36,6 +38,7 @@ import org.koitharu.kotatsu.core.db.migrations.Migration1To2
import org.koitharu.kotatsu.core.db.migrations.Migration20To21
import org.koitharu.kotatsu.core.db.migrations.Migration21To22
import org.koitharu.kotatsu.core.db.migrations.Migration22To23
import org.koitharu.kotatsu.core.db.migrations.Migration23To24
import org.koitharu.kotatsu.core.db.migrations.Migration2To3
import org.koitharu.kotatsu.core.db.migrations.Migration3To4
import org.koitharu.kotatsu.core.db.migrations.Migration4To5
@@ -63,14 +66,14 @@ import org.koitharu.kotatsu.tracker.data.TrackEntity
import org.koitharu.kotatsu.tracker.data.TrackLogEntity
import org.koitharu.kotatsu.tracker.data.TracksDao
const val DATABASE_VERSION = 23
const val DATABASE_VERSION = 24
@Database(
entities = [
MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class,
FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class,
TrackEntity::class, TrackLogEntity::class, SuggestionEntity::class, BookmarkEntity::class,
ScrobblingEntity::class, MangaSourceEntity::class, StatsEntity::class, LocalMangaIndexEntity::class,
MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class, ChapterEntity::class,
FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class, TrackEntity::class,
TrackLogEntity::class, SuggestionEntity::class, BookmarkEntity::class, ScrobblingEntity::class,
MangaSourceEntity::class, StatsEntity::class, LocalMangaIndexEntity::class,
],
version = DATABASE_VERSION,
)
@@ -103,6 +106,8 @@ abstract class MangaDatabase : RoomDatabase() {
abstract fun getStatsDao(): StatsDao
abstract fun getLocalMangaIndexDao(): LocalMangaIndexDao
abstract fun getChaptersDao(): ChaptersDao
}
fun getDatabaseMigrations(context: Context): Array<Migration> = arrayOf(
@@ -128,6 +133,7 @@ fun getDatabaseMigrations(context: Context): Array<Migration> = arrayOf(
Migration20To21(),
Migration21To22(),
Migration22To23(),
Migration23To24(),
)
fun MangaDatabase(context: Context): MangaDatabase = Room

View File

@@ -7,3 +7,4 @@ const val TABLE_FAVOURITE_CATEGORIES = "favourite_categories"
const val TABLE_HISTORY = "history"
const val TABLE_MANGA_TAGS = "manga_tags"
const val TABLE_SOURCES = "sources"
const val TABLE_CHAPTERS = "chapters"

View File

@@ -0,0 +1,29 @@
package org.koitharu.kotatsu.core.db.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Transaction
import org.koitharu.kotatsu.core.db.entity.ChapterEntity
@Dao
abstract class ChaptersDao {
@Query("SELECT * FROM chapters WHERE manga_id = :mangaId ORDER BY `index` ASC")
abstract suspend fun findAll(mangaId: Long): List<ChapterEntity>
@Query("DELETE FROM chapters WHERE manga_id = :mangaId")
abstract suspend fun deleteAll(mangaId: Long)
@Query("DELETE FROM chapters WHERE manga_id NOT IN (SELECT manga_id FROM history WHERE deleted_at = 0) AND manga_id NOT IN (SELECT manga_id FROM favourites WHERE deleted_at = 0)")
abstract suspend fun gc()
@Transaction
open suspend fun replaceAll(mangaId: Long, entities: Collection<ChapterEntity>) {
deleteAll(mangaId)
insert(entities)
}
@Insert
protected abstract suspend fun insert(entities: Collection<ChapterEntity>)
}

View File

@@ -20,6 +20,9 @@ abstract class MangaDao {
@Query("SELECT * FROM manga WHERE manga_id = :id")
abstract suspend fun find(id: Long): MangaWithTags?
@Query("SELECT EXISTS(SELECT * FROM manga WHERE manga_id = :id)")
abstract suspend operator fun contains(id: Long): Boolean
@Transaction
@Query("SELECT * FROM manga WHERE public_url = :publicUrl")
abstract suspend fun findByPublicUrl(publicUrl: String): MangaWithTags?

View File

@@ -0,0 +1,32 @@
package org.koitharu.kotatsu.core.db.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import org.koitharu.kotatsu.core.db.TABLE_CHAPTERS
@Entity(
tableName = TABLE_CHAPTERS,
primaryKeys = ["manga_id", "chapter_id"],
foreignKeys = [
ForeignKey(
entity = MangaEntity::class,
parentColumns = ["manga_id"],
childColumns = ["manga_id"],
onDelete = ForeignKey.CASCADE,
),
],
)
data class ChapterEntity(
@ColumnInfo(name = "chapter_id") val chapterId: Long,
@ColumnInfo(name = "manga_id") val mangaId: Long,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "number") val number: Float,
@ColumnInfo(name = "volume") val volume: Int,
@ColumnInfo(name = "url") val url: String,
@ColumnInfo(name = "scanlator") val scanlator: String?,
@ColumnInfo(name = "upload_date") val uploadDate: Long,
@ColumnInfo(name = "branch") val branch: String?,
@ColumnInfo(name = "source") val source: String,
@ColumnInfo(name = "index") val index: Int,
)

View File

@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.core.db.entity
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.util.ext.longHashCode
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaState
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.model.SortOrder
@@ -21,7 +22,7 @@ fun Collection<TagEntity>.toMangaTags() = mapToSet(TagEntity::toMangaTag)
fun Collection<TagEntity>.toMangaTagsList() = map(TagEntity::toMangaTag)
fun MangaEntity.toManga(tags: Set<MangaTag>) = Manga(
fun MangaEntity.toManga(tags: Set<MangaTag>, chapters: List<ChapterEntity>?) = Manga(
id = this.id,
title = this.title,
altTitle = this.altTitle,
@@ -35,12 +36,27 @@ fun MangaEntity.toManga(tags: Set<MangaTag>) = Manga(
author = this.author,
source = MangaSource(this.source),
tags = tags,
chapters = chapters?.toMangaChapters(),
)
fun MangaWithTags.toManga() = manga.toManga(tags.toMangaTags())
fun MangaWithTags.toManga(chapters: List<ChapterEntity>? = null) = manga.toManga(tags.toMangaTags(), chapters)
fun Collection<MangaWithTags>.toMangaList() = map { it.toManga() }
fun ChapterEntity.toMangaChapter() = MangaChapter(
id = chapterId,
name = name,
number = number,
volume = volume,
url = url,
scanlator = scanlator,
uploadDate = uploadDate,
branch = branch,
source = MangaSource(source),
)
fun Collection<ChapterEntity>.toMangaChapters() = map { it.toMangaChapter() }
// Model to entity
fun Manga.toEntity() = MangaEntity(
@@ -67,6 +83,22 @@ fun MangaTag.toEntity() = TagEntity(
fun Collection<MangaTag>.toEntities() = map(MangaTag::toEntity)
fun Iterable<IndexedValue<MangaChapter>>.toEntities(mangaId: Long) = map { (index, chapter) ->
ChapterEntity(
chapterId = chapter.id,
mangaId = mangaId,
name = chapter.name,
number = chapter.number,
volume = chapter.volume,
url = chapter.url,
scanlator = chapter.scanlator,
uploadDate = chapter.uploadDate,
branch = chapter.branch,
source = chapter.source.name,
index = index,
)
}
// Other
fun SortOrder(name: String, fallback: SortOrder): SortOrder = runCatching {

View File

@@ -0,0 +1,11 @@
package org.koitharu.kotatsu.core.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
class Migration23To24 : Migration(23, 24) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("CREATE TABLE IF NOT EXISTS `chapters` (`chapter_id` INTEGER NOT NULL, `manga_id` INTEGER NOT NULL, `name` TEXT NOT NULL, `number` REAL NOT NULL, `volume` INTEGER NOT NULL, `url` TEXT NOT NULL, `scanlator` TEXT, `upload_date` INTEGER NOT NULL, `branch` TEXT, `source` TEXT NOT NULL, `index` INTEGER NOT NULL, PRIMARY KEY(`manga_id`, `chapter_id`), FOREIGN KEY(`manga_id`) REFERENCES `manga`(`manga_id`) ON UPDATE NO ACTION ON DELETE CASCADE )")
}
}

View File

@@ -71,8 +71,13 @@ class MangaDataRepository @Inject constructor(
.distinctUntilChanged()
}
suspend fun findMangaById(mangaId: Long): Manga? {
return db.getMangaDao().find(mangaId)?.toManga()
suspend fun findMangaById(mangaId: Long, withChapters: Boolean): Manga? {
val chapters = if (withChapters) {
db.getChaptersDao().findAll(mangaId).takeUnless { it.isEmpty() }
} else {
null
}
return db.getMangaDao().find(mangaId)?.toManga(chapters)
}
suspend fun findMangaByPublicUrl(publicUrl: String): Manga? {
@@ -81,7 +86,7 @@ class MangaDataRepository @Inject constructor(
suspend fun resolveIntent(intent: MangaIntent): Manga? = when {
intent.manga != null -> intent.manga
intent.mangaId != 0L -> findMangaById(intent.mangaId)
intent.mangaId != 0L -> findMangaById(intent.mangaId, true)
intent.uri != null -> resolverProvider.get().resolve(intent.uri)
else -> null
}
@@ -98,10 +103,26 @@ class MangaDataRepository @Inject constructor(
val tags = manga.tags.toEntities()
db.getTagsDao().upsert(tags)
db.getMangaDao().upsert(manga.toEntity(), tags)
if (!manga.isLocal) {
manga.chapters?.let { chapters ->
db.getChaptersDao().replaceAll(manga.id, chapters.withIndex().toEntities(manga.id))
}
}
}
}
}
suspend fun updateChapters(manga: Manga) {
val chapters = manga.chapters
if (!chapters.isNullOrEmpty() && manga.id in db.getMangaDao()) {
db.getChaptersDao().replaceAll(manga.id, chapters.withIndex().toEntities(manga.id))
}
}
suspend fun gcChapters() {
db.getChaptersDao().gc()
}
suspend fun findTags(source: MangaSource): Set<MangaTag> {
return db.getTagsDao().findTags(source.name).toMangaTags()
}

View File

@@ -43,7 +43,14 @@ class DetailsLoadUseCase @Inject constructor(
operator fun invoke(intent: MangaIntent): Flow<MangaDetails> = channelFlow {
val manga = requireNotNull(mangaDataRepository.resolveIntent(intent)) {
"Cannot resolve intent $intent"
}.let { m ->
if (m.chapters.isNullOrEmpty()) {
getCachedDetails(m.id) ?: m
} else {
m
}
}
send(MangaDetails(manga, null, null, false))
val local = if (!manga.isLocal) {
async {
localMangaRepository.findSavedManga(manga)
@@ -51,9 +58,9 @@ class DetailsLoadUseCase @Inject constructor(
} else {
null
}
send(MangaDetails(manga, null, null, false))
try {
val details = getDetails(manga)
launch { mangaDataRepository.updateChapters(details) }
launch { updateTracker(details) }
send(
MangaDetails(
@@ -122,4 +129,8 @@ class DetailsLoadUseCase @Inject constructor(
}.onFailure { e ->
e.printStackTraceDebug()
}
private suspend fun getCachedDetails(mangaId: Long): Manga? = runCatchingCancellable {
mangaDataRepository.findMangaById(mangaId, withChapters = true)
}.getOrNull()
}

View File

@@ -226,14 +226,15 @@ class DetailsViewModel @Inject constructor(
private fun doLoad() = launchLoadingJob(Dispatchers.Default) {
detailsLoadUseCase.invoke(intent)
.onEachWhile {
if (it.allChapters.isEmpty()) {
return@onEachWhile false
if (it.allChapters.isNotEmpty()) {
val manga = it.toManga()
// find default branch
val hist = historyRepository.getOne(manga)
selectedBranch.value = manga.getPreferredBranch(hist)
true
} else {
false
}
val manga = it.toManga()
// find default branch
val hist = historyRepository.getOne(manga)
selectedBranch.value = manga.getPreferredBranch(hist)
true
}.collect {
mangaDetails.value = it
}

View File

@@ -289,7 +289,7 @@ class DownloadsViewModel @Inject constructor(
}
return cacheMutex.withLock {
mangaCache.getOrElse(mangaId) {
mangaDataRepository.findMangaById(mangaId)?.also {
mangaDataRepository.findMangaById(mangaId, withChapters = true)?.also {
mangaCache[mangaId] = it
} ?: return null
}

View File

@@ -120,7 +120,7 @@ class DownloadWorker @AssistedInject constructor(
override suspend fun doWork(): Result {
setForeground(getForegroundInfo())
val manga = mangaDataRepository.findMangaById(task.mangaId) ?: return Result.failure()
val manga = mangaDataRepository.findMangaById(task.mangaId, withChapters = true) ?: return Result.failure()
publishState(DownloadState(manga = manga, isIndeterminate = true).also { lastPublishedState = it })
val downloadedIds = getDoneChapters(manga)
return try {

View File

@@ -16,6 +16,6 @@ fun FavouriteCategoryEntity.toFavouriteCategory(id: Long = categoryId.toLong())
isVisibleInLibrary = isVisibleInLibrary,
)
fun FavouriteManga.toManga() = manga.toManga(tags.toMangaTags())
fun FavouriteManga.toManga() = manga.toManga(tags.toMangaTags(), null)
fun Collection<FavouriteManga>.toMangaList() = map { it.toManga() }

View File

@@ -199,6 +199,7 @@ class FavouritesRepository @Inject constructor(
db.getFavouritesDao().deleteAll(id)
db.getFavouriteCategoriesDao().delete(id)
}
db.getChaptersDao().gc()
}
}
@@ -238,6 +239,7 @@ class FavouritesRepository @Inject constructor(
for (id in ids) {
db.getFavouritesDao().delete(mangaId = id)
}
db.getChaptersDao().gc()
}
return ReversibleHandle { recoverToFavourites(ids) }
}
@@ -247,6 +249,7 @@ class FavouritesRepository @Inject constructor(
for (id in ids) {
db.getFavouritesDao().delete(categoryId = categoryId, mangaId = id)
}
db.getChaptersDao().gc()
}
return ReversibleHandle { recoverToCategory(categoryId, ids) }
}

View File

@@ -32,7 +32,7 @@ class LocalFavoritesObserver @Inject constructor(
limit: Int
): Flow<List<Manga>> = db.getFavouritesDao().observeAll(categoryId, order, filterOptions, limit).mapToLocal()
override fun toManga(e: FavouriteManga) = e.manga.toManga(e.tags.toMangaTags())
override fun toManga(e: FavouriteManga) = e.manga.toManga(e.tags.toMangaTags(), null)
override fun toResult(e: FavouriteManga, manga: Manga) = manga
}

View File

@@ -24,7 +24,7 @@ class HistoryLocalObserver @Inject constructor(
limit: Int
) = db.getHistoryDao().observeAll(order, filterOptions, limit).mapToLocal()
override fun toManga(e: HistoryWithManga) = e.manga.toManga(e.tags.toMangaTags())
override fun toManga(e: HistoryWithManga) = e.manga.toManga(e.tags.toMangaTags(), null)
override fun toResult(e: HistoryWithManga, manga: Manga) = MangaWithHistory(
manga = manga,

View File

@@ -49,7 +49,7 @@ class HistoryRepository @Inject constructor(
suspend fun getList(offset: Int, limit: Int): List<Manga> {
val entities = db.getHistoryDao().findAll(offset, limit)
return entities.map { it.manga.toManga(it.tags.toMangaTags()) }
return entities.map { it.toManga() }
}
suspend fun search(query: String, limit: Int): List<Manga> {
@@ -63,25 +63,25 @@ class HistoryRepository @Inject constructor(
suspend fun getLastOrNull(): Manga? {
val entity = db.getHistoryDao().findAll(0, 1).firstOrNull() ?: return null
return entity.manga.toManga(entity.tags.toMangaTags())
return entity.toManga()
}
fun observeLast(): Flow<Manga?> {
return db.getHistoryDao().observeAll(1).map {
val first = it.firstOrNull()
first?.manga?.toManga(first.tags.toMangaTags())
first?.toManga()
}
}
fun observeAll(): Flow<List<Manga>> {
return db.getHistoryDao().observeAll().mapItems {
it.manga.toManga(it.tags.toMangaTags())
it.toManga()
}
}
fun observeAll(limit: Int): Flow<List<Manga>> {
return db.getHistoryDao().observeAll(limit).mapItems {
it.manga.toManga(it.tags.toMangaTags())
it.toManga()
}
}
@@ -95,7 +95,7 @@ class HistoryRepository @Inject constructor(
}
return db.getHistoryDao().observeAll(order, filterOptions, limit).mapItems {
MangaWithHistory(
it.manga.toManga(it.tags.toMangaTags()),
it.toManga(),
it.history.toMangaHistory(),
)
}
@@ -156,16 +156,19 @@ class HistoryRepository @Inject constructor(
db.getHistoryDao().clear()
}
suspend fun delete(manga: Manga) {
suspend fun delete(manga: Manga) = db.withTransaction {
db.getHistoryDao().delete(manga.id)
mangaRepository.gcChapters()
}
suspend fun deleteAfter(minDate: Long) {
suspend fun deleteAfter(minDate: Long) = db.withTransaction {
db.getHistoryDao().deleteAfter(minDate)
mangaRepository.gcChapters()
}
suspend fun deleteNotFavorite() {
suspend fun deleteNotFavorite() = db.withTransaction {
db.getHistoryDao().deleteNotFavorite()
mangaRepository.gcChapters()
}
suspend fun delete(ids: Collection<Long>): ReversibleHandle {
@@ -173,6 +176,7 @@ class HistoryRepository @Inject constructor(
for (id in ids) {
db.getHistoryDao().delete(id)
}
mangaRepository.gcChapters()
}
return ReversibleHandle {
recover(ids)
@@ -185,7 +189,7 @@ class HistoryRepository @Inject constructor(
*/
suspend fun deleteOrSwap(manga: Manga, alternative: Manga?) {
if (alternative == null || db.getMangaDao().update(alternative.toEntity()) <= 0) {
db.getHistoryDao().delete(manga.id)
delete(manga)
}
}
@@ -229,4 +233,6 @@ class HistoryRepository @Inject constructor(
db.getHistoryDao().update(newEntity)
return newEntity
}
private fun HistoryWithManga.toManga() = manga.toManga(tags.toMangaTags(), null)
}

View File

@@ -32,17 +32,17 @@ class CoverRestoreInterceptor @Inject constructor(
val result = chain.proceed()
if (result is ErrorResult && result.throwable.shouldRestore()) {
request.extras[mangaKey]?.let {
if (restoreManga(it)) {
return chain.withRequest(request.newBuilder().build()).proceed()
return if (restoreManga(it)) {
chain.withRequest(request.newBuilder().build()).proceed()
} else {
return result
result
}
}
request.extras[bookmarkKey]?.let {
if (restoreBookmark(it)) {
return chain.withRequest(request.newBuilder().build()).proceed()
return if (restoreBookmark(it)) {
chain.withRequest(request.newBuilder().build()).proceed()
} else {
return result
result
}
}
}
@@ -66,7 +66,7 @@ class CoverRestoreInterceptor @Inject constructor(
}
private suspend fun restoreMangaImpl(manga: Manga): Boolean {
if (dataRepository.findMangaById(manga.id) == null || manga.isLocal) {
if (dataRepository.findMangaById(manga.id, withChapters = false) == null || manga.isLocal) {
return false
}
val repo = repositoryFactory.create(manga.source)

View File

@@ -33,7 +33,7 @@ class StatsRepository @Inject constructor(
var other = StatsRecord(null, 0)
val total = stats.values.sum()
for ((mangaEntity, duration) in stats) {
val manga = mangaEntity.toManga(emptySet())
val manga = mangaEntity.toManga(emptySet(), null)
val percent = duration.toDouble() / total
if (percent < 0.05) {
other = other.copy(duration = other.duration + duration)

View File

@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.suggestions.data.SuggestionEntity
import org.koitharu.kotatsu.suggestions.data.SuggestionWithManga
import javax.inject.Inject
class SuggestionRepository @Inject constructor(
@@ -23,25 +24,23 @@ class SuggestionRepository @Inject constructor(
fun observeAll(): Flow<List<Manga>> {
return db.getSuggestionDao().observeAll().mapItems {
it.manga.toManga(it.tags.toMangaTags())
it.toManga()
}
}
fun observeAll(limit: Int, filterOptions: Set<ListFilterOption>): Flow<List<Manga>> {
return db.getSuggestionDao().observeAll(limit, filterOptions).mapItems {
it.manga.toManga(it.tags.toMangaTags())
it.toManga()
}
}
suspend fun getRandom(): Manga? {
return db.getSuggestionDao().getRandom()?.let {
it.manga.toManga(it.tags.toMangaTags())
}
return db.getSuggestionDao().getRandom()?.toManga()
}
suspend fun getRandomList(limit: Int): List<Manga> {
return db.getSuggestionDao().getRandom(limit).map {
it.manga.toManga(it.tags.toMangaTags())
it.toManga()
}
}
@@ -80,4 +79,6 @@ class SuggestionRepository @Inject constructor(
}
}
}
private fun SuggestionWithManga.toManga() = manga.toManga(tags.toMangaTags(), null)
}

View File

@@ -10,7 +10,7 @@ fun TrackLogWithManga.toTrackingLogItem(): TrackingLogItem {
return TrackingLogItem(
id = trackLog.id,
chapters = chaptersList,
manga = manga.toManga(tags.toMangaTags()),
manga = manga.toManga(tags.toMangaTags(), null),
createdAt = Instant.ofEpochMilli(trackLog.createdAt),
isNew = trackLog.isUnread,
)

View File

@@ -60,7 +60,7 @@ class TrackingRepository @Inject constructor(
return db.getTracksDao().observeUpdatedManga(limit, filterOptions)
.mapItems {
MangaTracking(
manga = it.manga.toManga(it.tags.toMangaTags()),
manga = it.manga.toManga(it.tags.toMangaTags(), null),
lastChapterId = it.track.lastChapterId,
lastCheck = it.track.lastCheckTime.toInstantOrNull(),
lastChapterDate = it.track.lastChapterDate.toInstantOrNull(),
@@ -73,7 +73,7 @@ class TrackingRepository @Inject constructor(
suspend fun getTracks(offset: Int, limit: Int): List<MangaTracking> {
return db.getTracksDao().findAll(offset = offset, limit = limit).map {
MangaTracking(
manga = it.manga.toManga(emptySet()),
manga = it.manga.toManga(emptySet(), null),
lastChapterId = it.track.lastChapterId,
lastCheck = it.track.lastCheckTime.toInstantOrNull(),
lastChapterDate = it.track.lastChapterDate.toInstantOrNull(),

View File

@@ -25,7 +25,7 @@ class TrackerDebugViewModel @Inject constructor(
private fun List<TrackWithManga>.toUiList(): List<TrackDebugItem> = map {
TrackDebugItem(
manga = it.manga.toManga(emptySet()),
manga = it.manga.toManga(emptySet(), null),
lastChapterId = it.track.lastChapterId,
newChapters = it.track.newChapters,
lastCheckTime = it.track.lastCheckTime.toInstantOrNull(),

View File

@@ -43,7 +43,7 @@ transition = "1.5.1"
viewpager2 = "1.1.0"
webkit = "1.12.1"
workRuntime = "2.10.0"
workinspector = "1.0"
workinspector = "1.2"
[libraries]
acra-dialog = { module = "ch.acra:acra-dialog", version.ref = "acra" }