diff --git a/app/src/main/java/eu/kanade/data/manga/LibraryQuery.kt b/app/src/main/java/eu/kanade/data/manga/LibraryQuery.kt index ca54dbc92..7f42c1036 100644 --- a/app/src/main/java/eu/kanade/data/manga/LibraryQuery.kt +++ b/app/src/main/java/eu/kanade/data/manga/LibraryQuery.kt @@ -4,35 +4,40 @@ import com.squareup.sqldelight.Query import com.squareup.sqldelight.db.SqlCursor import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.internal.copyOnWriteList +import eu.kanade.data.listOfStringsAdapter +import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.data.updateStrategyAdapter -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import exh.source.MERGED_SOURCE_ID private val mapper = { cursor: SqlCursor -> - LibraryManga().apply { - id = cursor.getLong(0)!! - source = cursor.getLong(1)!! - url = cursor.getString(2)!! - artist = cursor.getString(3) - author = cursor.getString(4) - description = cursor.getString(5) - genre = cursor.getString(6) - title = cursor.getString(7)!! - status = cursor.getLong(8)!!.toInt() - thumbnail_url = cursor.getString(9) - favorite = cursor.getLong(10)!! == 1L - last_update = cursor.getLong(11) ?: 0 - initialized = cursor.getLong(13)!! == 1L - viewer_flags = cursor.getLong(14)!!.toInt() - chapter_flags = cursor.getLong(15)!!.toInt() - cover_last_modified = cursor.getLong(16)!! - date_added = cursor.getLong(17)!! - filtered_scanlators = cursor.getString(18) - update_strategy = updateStrategyAdapter.decode(cursor.getLong(19)!!) - unreadCount = cursor.getLong(20)!!.toInt() - readCount = cursor.getLong(21)!!.toInt() - category = cursor.getLong(22)!!.toInt() - } + LibraryManga( + manga = mangaMapper( + cursor.getLong(0)!!, + cursor.getLong(1)!!, + cursor.getString(2)!!, + cursor.getString(3), + cursor.getString(4), + cursor.getString(5), + cursor.getString(6)?.let(listOfStringsAdapter::decode), + cursor.getString(7)!!, + cursor.getLong(8)!!, + cursor.getString(9), + cursor.getLong(10)!! == 1L, + cursor.getLong(11) ?: 0, + null, + cursor.getLong(13)!! == 1L, + cursor.getLong(14)!!, + cursor.getLong(15)!!, + cursor.getLong(16)!!, + cursor.getLong(17)!!, + cursor.getString(18)?.let(listOfStringsAndAdapter::decode), + updateStrategyAdapter.decode(cursor.getLong(19)!!), + ), + unreadCount = cursor.getLong(20)!!, + readCount = cursor.getLong(21)!!, + category = cursor.getLong(22)!!, + ) } class LibraryQuery(val driver: SqlDriver) : Query(copyOnWriteList(), mapper) { diff --git a/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt index dc9affaf4..e115bffce 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt @@ -1,8 +1,7 @@ package eu.kanade.data.manga -import eu.kanade.data.listOfStringsAndAdapter +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.model.Manga -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.source.model.UpdateStrategy val mangaMapper: (Long, Long, String, String?, String?, String?, List?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List?, UpdateStrategy) -> Manga = @@ -35,29 +34,32 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List?, } val libraryManga: (Long, Long, String, String?, String?, String?, List?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List?, UpdateStrategy, Long, Long, Long) -> LibraryManga = - { _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, filtered_scanlators, update_strategy, unread_count, read_count, category -> - LibraryManga().apply { - this.id = _id - this.source = source - this.url = url - this.artist = artist - this.author = author - this.description = description - this.genre = genre?.joinToString() - this.title = title - this.status = status.toInt() - this.thumbnail_url = thumbnail_url - this.favorite = favorite - this.last_update = last_update ?: 0 - this.update_strategy = update_strategy - this.initialized = initialized - this.viewer_flags = viewer.toInt() - this.chapter_flags = chapter_flags.toInt() - this.cover_last_modified = cover_last_modified - this.date_added = date_added - this.filtered_scanlators = filtered_scanlators?.let(listOfStringsAndAdapter::encode) - this.unreadCount = unread_count.toInt() - this.readCount = read_count.toInt() - this.category = category.toInt() - } + { _id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, filteredScanlators, updateStrategy, unreadCount, readCount, category -> + LibraryManga( + manga = mangaMapper( + _id, + source, + url, + artist, + author, + description, + genre, + title, + status, + thumbnailUrl, + favorite, + lastUpdate, + nextUpdate, + initialized, + viewerFlags, + chapterFlags, + coverLastModified, + dateAdded, + filteredScanlators, + updateStrategy, + ), + category = category, + unreadCount = unreadCount, + readCount = readCount, + ) } diff --git a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt index e9a450521..911a4fd4d 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -5,10 +5,10 @@ import eu.kanade.data.DatabaseHandler import eu.kanade.data.listOfStringsAdapter import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.data.updateStrategyAdapter +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.manga.repository.MangaRepository -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.toLong import kotlinx.coroutines.flow.Flow diff --git a/app/src/main/java/eu/kanade/domain/library/model/LibraryManga.kt b/app/src/main/java/eu/kanade/domain/library/model/LibraryManga.kt new file mode 100644 index 000000000..9e9916697 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/library/model/LibraryManga.kt @@ -0,0 +1,16 @@ +package eu.kanade.domain.library.model + +import eu.kanade.domain.manga.model.Manga + +data class LibraryManga( + val manga: Manga, + val category: Long, + val unreadCount: Long, + val readCount: Long, +) { + val totalChapters + get() = readCount + unreadCount + + val hasStarted + get() = readCount > 0 +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt index e7e56401c..c5d5b12be 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt @@ -1,7 +1,7 @@ package eu.kanade.domain.manga.interactor +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.repository.MangaRepository -import eu.kanade.tachiyomi.data.database.models.LibraryManga import kotlinx.coroutines.flow.Flow class GetLibraryManga( diff --git a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt index 57334c995..eebc8d26f 100644 --- a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt +++ b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt @@ -1,8 +1,8 @@ package eu.kanade.domain.manga.repository +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.MangaUpdate -import eu.kanade.tachiyomi.data.database.models.LibraryManga import kotlinx.coroutines.flow.Flow interface MangaRepository { diff --git a/app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt b/app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt index 90be2d2c5..6c6dca7a7 100644 --- a/app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt @@ -4,12 +4,12 @@ import androidx.compose.animation.Crossfade import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import eu.kanade.domain.category.model.Category +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.presentation.components.LibraryBottomActionMenu import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.library.components.LibraryContent import eu.kanade.presentation.library.components.LibraryToolbar -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.ui.library.LibraryPresenter @@ -65,7 +65,7 @@ fun LibraryScreen( onChangeCategoryClicked = onChangeCategoryClicked, onMarkAsReadClicked = onMarkAsReadClicked, onMarkAsUnreadClicked = onMarkAsUnreadClicked, - onDownloadClicked = onDownloadClicked.takeIf { presenter.selection.none { it.source == LocalSource.ID } }, + onDownloadClicked = onDownloadClicked.takeIf { presenter.selection.none { it.manga.source == LocalSource.ID } }, onDeleteClicked = onDeleteClicked, // SY --> onClickCleanTitles = onClickCleanTitles.takeIf { presenter.showCleanTitles }, diff --git a/app/src/main/java/eu/kanade/presentation/library/LibraryState.kt b/app/src/main/java/eu/kanade/presentation/library/LibraryState.kt index d17fa54c7..08cbaa8c4 100644 --- a/app/src/main/java/eu/kanade/presentation/library/LibraryState.kt +++ b/app/src/main/java/eu/kanade/presentation/library/LibraryState.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import eu.kanade.domain.category.model.Category import eu.kanade.domain.library.model.LibraryGroup -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryPresenter import exh.source.PERV_EDEN_EN_SOURCE_ID import exh.source.PERV_EDEN_IT_SOURCE_ID @@ -55,14 +55,14 @@ class LibraryStateImpl : LibraryState { override var showSyncExh: Boolean by mutableStateOf(true) override val showCleanTitles: Boolean by derivedStateOf { selection.any { - it.isEhBasedManga() || - it.source in nHentaiSourceIds || - it.source == PERV_EDEN_EN_SOURCE_ID || - it.source == PERV_EDEN_IT_SOURCE_ID + it.manga.isEhBasedManga() || + it.manga.source in nHentaiSourceIds || + it.manga.source == PERV_EDEN_EN_SOURCE_ID || + it.manga.source == PERV_EDEN_IT_SOURCE_ID } } override val showAddToMangadex: Boolean by derivedStateOf { - selection.any { it.source in mangaDexSourceIds } + selection.any { it.manga.source in mangaDexSourceIds } } // SY <-- } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt index 6862f027f..894f1ad34 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt @@ -12,8 +12,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.model.MangaCover -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem @Composable @@ -41,7 +41,7 @@ fun LibraryComfortableGrid( ) { libraryItem -> LibraryComfortableGridItem( libraryItem, - libraryItem.manga in selection, + libraryItem.libraryManga in selection, onClick, onLongClick, // SY --> @@ -60,35 +60,36 @@ fun LibraryComfortableGridItem( onLongClick: (LibraryManga) -> Unit, onOpenReader: (LibraryManga) -> Unit, ) { - val manga = item.manga + val libraryManga = item.libraryManga + val manga = libraryManga.manga LibraryGridItemSelectable(isSelected = isSelected) { Column( modifier = Modifier .combinedClickable( onClick = { - onClick(manga) + onClick(libraryManga) }, onLongClick = { - onLongClick(manga) + onLongClick(libraryManga) }, ), ) { LibraryGridCover( mangaCover = MangaCover( - manga.id!!, + manga.id, manga.source, manga.favorite, - manga.thumbnail_url, - manga.cover_last_modified, + manga.thumbnailUrl, + manga.coverLastModified, ), downloadCount = item.downloadCount, unreadCount = item.unreadCount, isLocal = item.isLocal, language = item.sourceLanguage, // SY --> - showPlayButton = item.startReadingButton && item.manga.unreadCount > 0, + showPlayButton = item.startReadingButton && item.libraryManga.unreadCount > 0, onOpenReader = { - onOpenReader(manga) + onOpenReader(item.libraryManga) }, // SY <-- ) diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt index 5625b59be..cac304bc4 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem @Composable @@ -50,7 +50,7 @@ fun LibraryCompactGrid( ) { libraryItem -> LibraryCompactGridItem( item = libraryItem, - isSelected = libraryItem.manga in selection, + isSelected = libraryItem.libraryManga in selection, onClick = onClick, onLongClick = onLongClick, // SY --> @@ -71,34 +71,35 @@ fun LibraryCompactGridItem( onOpenReader: (LibraryManga) -> Unit, // SY <-- ) { - val manga = item.manga + val libraryManga = item.libraryManga + val manga = libraryManga.manga LibraryGridCover( modifier = Modifier .selectedOutline(isSelected) .combinedClickable( onClick = { - onClick(manga) + onClick(libraryManga) }, onLongClick = { - onLongClick(manga) + onLongClick(libraryManga) }, ), mangaCover = eu.kanade.domain.manga.model.MangaCover( - manga.id!!, + manga.id, manga.source, manga.favorite, - manga.thumbnail_url, - manga.cover_last_modified, + manga.thumbnailUrl, + manga.coverLastModified, ), downloadCount = item.downloadCount, unreadCount = item.unreadCount, isLocal = item.isLocal, language = item.sourceLanguage, // SY --> - showPlayButton = item.startReadingButton && item.manga.unreadCount > 0, + showPlayButton = item.startReadingButton && item.libraryManga.unreadCount > 0, playButtonPosition = PlayButtonPosition.Top, onOpenReader = { - onOpenReader(manga) + onOpenReader(item.libraryManga) }, // SY <-- ) { diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt index c2140a32a..22a971551 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt @@ -21,11 +21,11 @@ import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import eu.kanade.core.prefs.PreferenceMutableState import eu.kanade.domain.category.model.Category import eu.kanade.domain.library.model.LibraryDisplayMode +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.presentation.components.EmptyScreen import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.library.LibraryState import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem import eu.kanade.tachiyomi.widget.EmptyView import kotlinx.coroutines.delay @@ -86,7 +86,7 @@ fun LibraryContent( val onClickManga = { manga: LibraryManga -> if (state.selectionMode.not()) { - onMangaClicked(manga.id!!) + onMangaClicked(manga.manga.id) } else { onToggleSelection(manga) } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryCoverOnlyGrid.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryCoverOnlyGrid.kt index 9a95b30fa..7c997826c 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryCoverOnlyGrid.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryCoverOnlyGrid.kt @@ -5,7 +5,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.grid.items import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem @Composable @@ -33,7 +33,7 @@ fun LibraryCoverOnlyGrid( ) { libraryItem -> LibraryCoverOnlyGridItem( item = libraryItem, - isSelected = libraryItem.manga in selection, + isSelected = libraryItem.libraryManga in selection, onClick = onClick, onLongClick = onLongClick, // SY --> @@ -54,33 +54,34 @@ fun LibraryCoverOnlyGridItem( onOpenReader: (LibraryManga) -> Unit, // SY <-- ) { - val manga = item.manga + val libraryManga = item.libraryManga + val manga = libraryManga.manga LibraryGridCover( modifier = Modifier .selectedOutline(isSelected) .combinedClickable( onClick = { - onClick(manga) + onClick(libraryManga) }, onLongClick = { - onLongClick(manga) + onLongClick(libraryManga) }, ), mangaCover = eu.kanade.domain.manga.model.MangaCover( - manga.id!!, + manga.id, manga.source, manga.favorite, - manga.thumbnail_url, - manga.cover_last_modified, + manga.thumbnailUrl, + manga.coverLastModified, ), downloadCount = item.downloadCount, unreadCount = item.unreadCount, isLocal = item.isLocal, language = item.sourceLanguage, // SY --> - showPlayButton = item.startReadingButton && item.manga.unreadCount > 0, + showPlayButton = item.startReadingButton && item.libraryManga.unreadCount > 0, onOpenReader = { - onOpenReader(manga) + onOpenReader(item.libraryManga) }, // SY <-- ) diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryGridCover.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryGridCover.kt index 71aa862f3..6e4f63c35 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryGridCover.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryGridCover.kt @@ -80,8 +80,8 @@ fun MangaGridCover( fun LibraryGridCover( modifier: Modifier = Modifier, mangaCover: eu.kanade.domain.manga.model.MangaCover, - downloadCount: Int, - unreadCount: Int, + downloadCount: Long, + unreadCount: Long, isLocal: Boolean, language: String, // SY --> diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryList.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryList.kt index 79477be9c..577915e0d 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryList.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryList.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.manga.model.MangaCover import eu.kanade.presentation.components.Badge import eu.kanade.presentation.components.BadgeGroup @@ -28,7 +29,6 @@ import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.selectedBackground import eu.kanade.presentation.util.verticalPadding import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem @Composable @@ -61,7 +61,7 @@ fun LibraryList( ) { libraryItem -> LibraryListItem( item = libraryItem, - isSelected = libraryItem.manga in selection, + isSelected = libraryItem.libraryManga in selection, onClick = onClick, onLongClick = onLongClick, ) @@ -76,19 +76,20 @@ fun LibraryListItem( onClick: (LibraryManga) -> Unit, onLongClick: (LibraryManga) -> Unit, ) { - val manga = item.manga + val libraryManga = item.libraryManga + val manga = libraryManga.manga MangaListItem( modifier = Modifier.selectedBackground(isSelected), title = manga.title, cover = MangaCover( - manga.id!!, + manga.id, manga.source, manga.favorite, - manga.thumbnail_url, - manga.cover_last_modified, + manga.thumbnailUrl, + manga.coverLastModified, ), - onClick = { onClick(manga) }, - onLongClick = { onLongClick(manga) }, + onClick = { onClick(libraryManga) }, + onLongClick = { onLongClick(libraryManga) }, ) { if (item.downloadCount > 0) { Badge( diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt index f0e7abcda..b53dfef39 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt @@ -13,7 +13,7 @@ import com.google.accompanist.pager.HorizontalPager import com.google.accompanist.pager.PagerState import eu.kanade.core.prefs.PreferenceMutableState import eu.kanade.domain.library.model.LibraryDisplayMode -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.tachiyomi.ui.library.LibraryItem @Composable diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt deleted file mode 100644 index 2a97c80d8..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt +++ /dev/null @@ -1,41 +0,0 @@ -package eu.kanade.tachiyomi.data.database.models - -class LibraryManga : MangaImpl() { - - var unreadCount: Int = 0 - var readCount: Int = 0 - - val totalChapters - get() = readCount + unreadCount - - val hasStarted - get() = readCount > 0 - - var category: Int = 0 - - // SY --> - var read: Int = 0 - // SY <-- - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is LibraryManga) return false - if (!super.equals(other)) return false - - if (unreadCount != other.unreadCount) return false - if (readCount != other.readCount) return false - if (category != other.category) return false - if (read != other.read) return false - - return true - } - - override fun hashCode(): Int { - var result = super.hashCode() - result = 31 * result + unreadCount - result = 31 * result + readCount - result = 31 * result + category - result = 31 * result + read - return result - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index d62cd4b5f..4c5a93ca3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -21,7 +21,6 @@ import eu.kanade.tachiyomi.data.download.Downloader import eu.kanade.tachiyomi.data.notification.NotificationHandler import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.lang.launchUI @@ -71,7 +70,7 @@ class LibraryUpdateNotifier(private val context: Context) { * @param current the current progress. * @param total the total progress. */ - fun showProgressNotification(manga: List */SManga/* SY <-- */>, current: Int, total: Int) { + fun showProgressNotification(manga: List, current: Int, total: Int) { if (preferences.hideNotificationContent().get()) { progressNotificationBuilder .setContentTitle(context.getString(R.string.notification_check_updates)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 3d98687c0..d9d244ac7 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -17,6 +17,7 @@ import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.download.service.DownloadPreferences import eu.kanade.domain.library.model.GroupLibraryMode import eu.kanade.domain.library.model.LibraryGroup +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.library.service.LibraryPreferences import eu.kanade.domain.manga.interactor.GetFavorites import eu.kanade.domain.manga.interactor.GetLibraryManga @@ -25,6 +26,7 @@ import eu.kanade.domain.manga.interactor.GetMergedMangaForDownloading import eu.kanade.domain.manga.interactor.InsertFlatMetadata import eu.kanade.domain.manga.interactor.InsertManga import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.domain.track.interactor.GetTracks @@ -34,10 +36,7 @@ import eu.kanade.domain.track.model.toDomainTrack import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.LibraryManga -import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.toDomainChapter -import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start @@ -94,7 +93,6 @@ import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger import eu.kanade.domain.chapter.model.Chapter as DomainChapter -import eu.kanade.domain.manga.model.Manga as DomainManga /** * This class will take care of updating the chapters of the manga from the library. It can be @@ -308,28 +306,28 @@ class LibraryUpdateService( * * @param categoryId the ID of the category to update, or -1 if no category specified. */ - fun addMangaToQueue(categoryId: Long, group: Int, groupExtra: String?) { + private fun addMangaToQueue(categoryId: Long, group: Int, groupExtra: String?) { val libraryManga = runBlocking { getLibraryManga.await() } // SY --> val groupLibraryUpdateType = libraryPreferences.groupLibraryUpdateType().get() // SY <-- val listToUpdate = if (categoryId != -1L) { - libraryManga.filter { it.category.toLong() == categoryId } + libraryManga.filter { it.category == categoryId } // SY --> } else if ( group == LibraryGroup.BY_DEFAULT || groupLibraryUpdateType == GroupLibraryMode.GLOBAL || (groupLibraryUpdateType == GroupLibraryMode.ALL_BUT_UNGROUPED && group == LibraryGroup.UNGROUPED) ) { - val categoriesToUpdate = libraryPreferences.libraryUpdateCategories().get().map(String::toInt) + val categoriesToUpdate = libraryPreferences.libraryUpdateCategories().get().map(String::toLong) val listToInclude = if (categoriesToUpdate.isNotEmpty()) { libraryManga.filter { it.category in categoriesToUpdate } } else { libraryManga } - val categoriesToExclude = libraryPreferences.libraryUpdateCategoriesExclude().get().map(String::toInt) + val categoriesToExclude = libraryPreferences.libraryUpdateCategoriesExclude().get().map { it.toLong() } val listToExclude = if (categoriesToExclude.isNotEmpty()) { libraryManga.filter { it.category in categoriesToExclude }.toSet() } else { @@ -343,7 +341,7 @@ class LibraryUpdateService( val trackingExtra = groupExtra?.toIntOrNull() ?: -1 val tracks = runBlocking { getTracks.await() }.groupBy { it.mangaId } - libraryManga.filter { manga -> + libraryManga.filter { (manga) -> val status = tracks[manga.id]?.firstNotNullOfOrNull { track -> TrackStatus.parseTrackerStatus(track.syncId, track.status) } ?: TrackStatus.OTHER @@ -352,17 +350,17 @@ class LibraryUpdateService( } LibraryGroup.BY_SOURCE -> { val sourceExtra = groupExtra?.nullIfBlank()?.toIntOrNull() - val source = libraryManga.map { it.source } + val source = libraryManga.map { it.manga.source } .distinct() .sorted() .getOrNull(sourceExtra ?: -1) - if (source != null) libraryManga.filter { it.source == source } else emptyList() + if (source != null) libraryManga.filter { it.manga.source == source } else emptyList() } LibraryGroup.BY_STATUS -> { - val statusExtra = groupExtra?.toIntOrNull() ?: -1 + val statusExtra = groupExtra?.toLongOrNull() ?: -1 libraryManga.filter { - it.status == statusExtra + it.manga.status == statusExtra } } LibraryGroup.UNGROUPED -> libraryManga @@ -372,12 +370,12 @@ class LibraryUpdateService( } mangaToUpdate = listToUpdate - .distinctBy { it.id } - .sortedBy { it.title } + .distinctBy { it.manga.id } + .sortedBy { it.manga.title } // Warn when excessively checking a single source val maxUpdatesFromSource = mangaToUpdate - .groupBy { it.source } + .groupBy { it.manga.source } .filterKeys { sourceManager.get(it) !is UnmeteredSource } .maxOfOrNull { it.value.size } ?: 0 if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { @@ -396,8 +394,8 @@ class LibraryUpdateService( private suspend fun updateChapterList() { val semaphore = Semaphore(5) val progressCount = AtomicInteger(0) - val currentlyUpdatingManga = CopyOnWriteArrayList() - val newUpdates = CopyOnWriteArrayList>>() + val currentlyUpdatingManga = CopyOnWriteArrayList() + val newUpdates = CopyOnWriteArrayList>>() val skippedUpdates = CopyOnWriteArrayList>() val failedUpdates = CopyOnWriteArrayList>() val hasDownloads = AtomicBoolean(false) @@ -406,61 +404,59 @@ class LibraryUpdateService( val restrictions = libraryPreferences.libraryUpdateMangaRestriction().get() withIOContext { - mangaToUpdate.groupBy { it.source } + mangaToUpdate.groupBy { it.manga.source } .filterNot { it.key in LIBRARY_UPDATE_EXCLUDED_SOURCES } .values .map { mangaInSource -> async { semaphore.withPermit { - mangaInSource.forEach { manga -> + mangaInSource.forEach { libraryManga -> + val manga = libraryManga.manga if (updateJob?.isActive != true) { return@async } - // Don't continue to update if manga not in library - manga.id?.let { getManga.await(it) } ?: return@forEach + // Don't continue to update if manga is not in library + manga.id.let { getManga.await(it) } ?: return@forEach withUpdateNotification( currentlyUpdatingManga, progressCount, manga, - ) { mangaWithNotif -> + ) { try { when { - MANGA_NON_COMPLETED in restrictions && mangaWithNotif.status == SManga.COMPLETED -> - skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_completed)) + MANGA_NON_COMPLETED in restrictions && manga.status.toInt() == SManga.COMPLETED -> + skippedUpdates.add(manga to getString(R.string.skipped_reason_completed)) - MANGA_HAS_UNREAD in restrictions && mangaWithNotif.unreadCount != 0 -> - skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_caught_up)) + MANGA_HAS_UNREAD in restrictions && libraryManga.unreadCount != 0L -> + skippedUpdates.add(manga to getString(R.string.skipped_reason_not_caught_up)) - MANGA_NON_READ in restrictions && mangaWithNotif.totalChapters > 0 && !mangaWithNotif.hasStarted -> - skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_started)) + MANGA_NON_READ in restrictions && libraryManga.totalChapters > 0L && !libraryManga.hasStarted -> + skippedUpdates.add(manga to getString(R.string.skipped_reason_not_started)) - mangaWithNotif.update_strategy != UpdateStrategy.ALWAYS_UPDATE -> - skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_always_update)) + manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE -> + skippedUpdates.add(manga to getString(R.string.skipped_reason_not_always_update)) else -> { - // Convert to the manga that contains new chapters - mangaWithNotif.toDomainManga()?.let { domainManga -> - val newChapters = updateManga(domainManga, loggedServices) - val newDbChapters = newChapters.map { it.toDbChapter() } + val newChapters = updateManga(manga, loggedServices) + val newDbChapters = newChapters.map { it.toDbChapter() } - if (newChapters.isNotEmpty()) { - val categoryIds = getCategories.await(domainManga.id).map { it.id } - if (domainManga.shouldDownloadNewChapters(categoryIds, downloadPreferences)) { - downloadChapters(mangaWithNotif, newDbChapters) - hasDownloads.set(true) - } - - // Convert to the manga that contains new chapters - newUpdates.add( - mangaWithNotif.toDomainManga()!! to - newDbChapters - .map { it.toDomainChapter()!! } - .sortedByDescending { it.sourceOrder } - .toTypedArray(), - ) + if (newChapters.isNotEmpty()) { + val categoryIds = getCategories.await(manga.id).map { it.id } + if (manga.shouldDownloadNewChapters(categoryIds, downloadPreferences)) { + downloadChapters(manga, newDbChapters) + hasDownloads.set(true) } + + // Convert to the manga that contains new chapters + newUpdates.add( + manga to + newDbChapters + .map { it.toDomainChapter()!! } + .sortedByDescending { it.sourceOrder } + .toTypedArray(), + ) } } } @@ -471,11 +467,11 @@ class LibraryUpdateService( is SourceManager.SourceNotInstalledException -> getString(R.string.loader_not_implemented_error) else -> e.message } - failedUpdates.add(mangaWithNotif to errorMessage) + failedUpdates.add(manga to errorMessage) } if (libraryPreferences.autoUpdateTrackers().get()) { - updateTrackings(mangaWithNotif, loggedServices) + updateTrackings(manga, loggedServices) } } } @@ -513,7 +509,7 @@ class LibraryUpdateService( // may don't like it and they could ban the user. // SY --> if (manga.source == MERGED_SOURCE_ID) { - val downloadingManga = runBlocking { getMergedMangaForDownloading.await(manga.id!!) } + val downloadingManga = runBlocking { getMergedMangaForDownloading.await(manga.id) } .associateBy { it.id } chapters.groupBy { it.manga_id } .forEach { @@ -527,7 +523,7 @@ class LibraryUpdateService( return } // SY <-- - downloadManager.downloadChapters(manga.toDomainManga()!!, chapters, false) + downloadManager.downloadChapters(manga, chapters, false) } /** @@ -536,7 +532,7 @@ class LibraryUpdateService( * @param manga the manga to update. * @return a pair of the inserted and removed chapters. */ - private suspend fun updateManga(manga: DomainManga, loggedServices: List): List { + private suspend fun updateManga(manga: Manga, loggedServices: List): List { val source = sourceManager.getOrStub(manga.source) // Update manga metadata if needed @@ -578,15 +574,16 @@ class LibraryUpdateService( private suspend fun updateCovers() { val semaphore = Semaphore(5) val progressCount = AtomicInteger(0) - val currentlyUpdatingManga = CopyOnWriteArrayList() + val currentlyUpdatingManga = CopyOnWriteArrayList() withIOContext { - mangaToUpdate.groupBy { it.source } + mangaToUpdate.groupBy { it.manga.source } .values .map { mangaInSource -> async { semaphore.withPermit { - mangaInSource.forEach { manga -> + mangaInSource.forEach { libraryManga -> + val manga = libraryManga.manga if (updateJob?.isActive != true) { return@async } @@ -595,14 +592,14 @@ class LibraryUpdateService( currentlyUpdatingManga, progressCount, manga, - ) { mangaWithNotif -> - val source = sourceManager.get(mangaWithNotif.source) ?: return@withUpdateNotification + ) { + val source = sourceManager.get(manga.source) ?: return@withUpdateNotification try { - val networkManga = source.getMangaDetails(mangaWithNotif.copy()) - mangaWithNotif.prepUpdateCover(coverCache, networkManga, true) - mangaWithNotif.copyFrom(networkManga) + val networkManga = source.getMangaDetails(manga.toSManga()) + val updatedManga = manga.prepUpdateCover(coverCache, networkManga, true) + .copyFrom(networkManga) try { - updateManga.await(mangaWithNotif.toDomainManga()!!.toMangaUpdate()) + updateManga.await(updatedManga.toMangaUpdate()) } catch (e: Exception) { logcat(LogPriority.ERROR) { "Manga doesn't exist anymore" } } @@ -629,7 +626,8 @@ class LibraryUpdateService( var progressCount = 0 val loggedServices = trackManager.services.filter { it.isLogged } - mangaToUpdate.forEach { manga -> + mangaToUpdate.forEach { libraryManga -> + val manga = libraryManga.manga if (updateJob?.isActive != true) { return } @@ -643,8 +641,8 @@ class LibraryUpdateService( notifier.cancelProgressNotification() } - private suspend fun updateTrackings(manga: LibraryManga, loggedServices: List) { - getTracks.await(manga.id!!) + private suspend fun updateTrackings(manga: Manga, loggedServices: List) { + getTracks.await(manga.id) .map { track -> supervisorScope { async { @@ -655,7 +653,7 @@ class LibraryUpdateService( insertTrack.await(updatedTrack.toDomainTrack()!!) if (service is EnhancedTrackService) { - val chapters = getChapterByMangaId.await(manga.id!!) + val chapters = getChapterByMangaId.await(manga.id) syncChaptersWithTrackServiceTwoWay.await(chapters, track, service) } } catch (e: Throwable) { @@ -670,10 +668,10 @@ class LibraryUpdateService( } private suspend fun withUpdateNotification( - updatingManga: CopyOnWriteArrayList, + updatingManga: CopyOnWriteArrayList, completed: AtomicInteger, - manga: LibraryManga, - block: suspend (LibraryManga) -> Unit, + manga: Manga, + block: suspend () -> Unit, ) { if (updateJob?.isActive != true) { return @@ -686,7 +684,7 @@ class LibraryUpdateService( mangaToUpdate.size, ) - block(manga) + block() if (updateJob?.isActive != true) { return @@ -723,21 +721,20 @@ class LibraryUpdateService( } count++ - notifier.showProgressNotification(listOf(networkManga), count, size) + notifier.showProgressNotification(listOf(Manga.create().copy(ogTitle = networkManga.title)), count, size) var dbManga = getManga.await(networkManga.url, mangaDex.id) if (dbManga == null) { - val newManga = Manga.create( - networkManga.url, - networkManga.title, - mangaDex.id, + val newManga = Manga.create().copy( + url = networkManga.url, + ogTitle = networkManga.title, + source = mangaDex.id, + favorite = true, + dateAdded = System.currentTimeMillis(), ) - newManga.favorite = true - newManga.date_added = System.currentTimeMillis() - newManga.id = -1 val result = runBlocking { - val id = insertManga.await(newManga.toDomainManga()!!) + val id = insertManga.await(newManga) getManga.await(id!!) } dbManga = result ?: return @@ -768,7 +765,7 @@ class LibraryUpdateService( } count++ - notifier.showProgressNotification(listOf(manga.toDbManga()), count, listManga.size) + notifier.showProgressNotification(listOf(manga), count, listManga.size) // Get this manga's trackers from the database val dbTracks = getTracks.await(manga.id) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index c4f1e0d25..d6fe10c29 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -21,7 +21,6 @@ import eu.kanade.presentation.components.ChangeCategoryDialog import eu.kanade.presentation.components.DeleteLibraryMangaDialog import eu.kanade.presentation.library.LibraryScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.ui.base.controller.FullComposeController import eu.kanade.tachiyomi.ui.base.controller.RootController @@ -115,8 +114,8 @@ class LibraryController( onClickCleanTitles = ::cleanTitles, onClickMigrate = { val selectedMangaIds = presenter.selection - .filterNot { it.source == MERGED_SOURCE_ID } - .mapNotNull { it.id } + .filterNot { it.manga.source == MERGED_SOURCE_ID } + .map { it.manga.id } presenter.clearSelection() if (selectedMangaIds.isNotEmpty()) { PreMigrationController.navigateToMigration( @@ -130,7 +129,7 @@ class LibraryController( }, onClickAddToMangaDex = ::pushToMdList, onOpenReader = { - startReading(it.toDomainManga()!!) + startReading(it.manga) }, onClickSyncExh = { // TODO @@ -296,7 +295,7 @@ class LibraryController( private fun showMangaCategoriesDialog() { viewScope.launchIO { // Create a copy of selected manga - val mangaList = presenter.selection.mapNotNull { it.toDomainManga() }.toList() + val mangaList = presenter.selection.map { it.manga } // Hide the default category because it has a different behavior than the ones from db. val categories = presenter.ogCategories.filter { it.id != 0L } // SY <-- @@ -318,28 +317,28 @@ class LibraryController( private fun downloadUnreadChapters() { val mangaList = presenter.selection.toList() - presenter.downloadUnreadChapters(mangaList.mapNotNull { it.toDomainManga() }) + presenter.downloadUnreadChapters(mangaList.map { it.manga }) presenter.clearSelection() } private fun markReadStatus(read: Boolean) { val mangaList = presenter.selection.toList() - presenter.markReadStatus(mangaList.mapNotNull { it.toDomainManga() }, read) + presenter.markReadStatus(mangaList.map { it.manga }, read) presenter.clearSelection() } private fun showDeleteMangaDialog() { - val mangaList = presenter.selection.mapNotNull { it.toDomainManga() }.toList() + val mangaList = presenter.selection.map { it.manga } presenter.dialog = LibraryPresenter.Dialog.DeleteManga(mangaList) } // SY --> private fun cleanTitles() { val mangas = presenter.selection.filter { - it.isEhBasedManga() || - it.source in nHentaiSourceIds || - it.source == PERV_EDEN_EN_SOURCE_ID || - it.source == PERV_EDEN_IT_SOURCE_ID + it.manga.isEhBasedManga() || + it.manga.source in nHentaiSourceIds || + it.manga.source == PERV_EDEN_EN_SOURCE_ID || + it.manga.source == PERV_EDEN_IT_SOURCE_ID } presenter.cleanTitles(mangas) presenter.clearSelection() @@ -347,7 +346,7 @@ class LibraryController( private fun pushToMdList() { val mangas = presenter.selection.filter { - it.source in mangaDexSourceIds + it.manga.source in mangaDexSourceIds } presenter.syncMangaToDex(mangas) presenter.clearSelection() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index dae7874e1..86ee0af01 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -1,18 +1,19 @@ package eu.kanade.tachiyomi.ui.library -import eu.kanade.tachiyomi.data.database.models.LibraryManga +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.getNameForMangaInfo import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get class LibraryItem( - val manga: LibraryManga, + val libraryManga: LibraryManga, private val sourceManager: SourceManager = Injekt.get(), ) { var displayMode: Long = -1 - var downloadCount = -1 - var unreadCount = -1 + var downloadCount: Long = -1 + var unreadCount: Long = -1 var isLocal = false var sourceLanguage = "" @@ -27,12 +28,12 @@ class LibraryItem( * @return true if the manga should be included, false otherwise. */ fun filter(constraint: String): Boolean { - val sourceName by lazy { sourceManager.getOrStub(manga.source).name } - val genres by lazy { manga.getGenres() } - return manga.title.contains(constraint, true) || - (manga.author?.contains(constraint, true) ?: false) || - (manga.artist?.contains(constraint, true) ?: false) || - (manga.description?.contains(constraint, true) ?: false) || + val sourceName by lazy { sourceManager.getOrStub(libraryManga.manga.source).getNameForMangaInfo(null) } + val genres by lazy { libraryManga.manga.genre } + return libraryManga.manga.title.contains(constraint, true) || + (libraryManga.manga.author?.contains(constraint, true) ?: false) || + (libraryManga.manga.artist?.contains(constraint, true) ?: false) || + (libraryManga.manga.description?.contains(constraint, true) ?: false) || if (constraint.contains(",")) { constraint.split(",").all { containsSourceOrGenre(it.trim(), sourceName, genres) } } else { @@ -76,7 +77,7 @@ class LibraryItem( other as LibraryItem - if (manga != other.manga) return false + if (libraryManga != other.libraryManga) return false if (sourceManager != other.sourceManager) return false if (displayMode != other.displayMode) return false if (downloadCount != other.downloadCount) return false @@ -88,11 +89,11 @@ class LibraryItem( } override fun hashCode(): Int { - var result = manga.hashCode() + var result = libraryManga.hashCode() result = 31 * result + sourceManager.hashCode() result = 31 * result + displayMode.hashCode() - result = 31 * result + downloadCount - result = 31 * result + unreadCount + result = 31 * result + downloadCount.toInt() + result = 31 * result + unreadCount.toInt() result = 31 * result + isLocal.hashCode() result = 31 * result + sourceLanguage.hashCode() return result diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index fbdb17bed..7d423794c 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -30,6 +30,7 @@ import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.library.model.LibraryDisplayMode import eu.kanade.domain.library.model.LibraryGroup +import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.library.model.LibrarySort import eu.kanade.domain.library.model.display import eu.kanade.domain.library.model.sort @@ -52,7 +53,6 @@ import eu.kanade.presentation.library.LibraryStateImpl import eu.kanade.presentation.library.components.LibraryToolbarTitle import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.library.CustomMangaManager @@ -286,9 +286,9 @@ class LibraryPresenter( val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item -> if (!downloadedOnly && filterDownloaded == State.IGNORE.value) return@downloaded true val isDownloaded = when { - item.manga.toDomainManga()!!.isLocal() -> true - item.downloadCount != -1 -> item.downloadCount > 0 - else -> downloadManager.getDownloadCount(item.manga.toDomainManga()!!) > 0 + item.libraryManga.manga.isLocal() -> true + item.downloadCount != -1L -> item.downloadCount > 0 + else -> downloadManager.getDownloadCount(item.libraryManga.manga) > 0 } return@downloaded if (downloadedOnly || filterDownloaded == State.INCLUDE.value) { @@ -300,7 +300,7 @@ class LibraryPresenter( val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item -> if (filterUnread == State.IGNORE.value) return@unread true - val isUnread = item.manga.unreadCount != 0 + val isUnread = item.libraryManga.unreadCount != 0L return@unread if (filterUnread == State.INCLUDE.value) { isUnread @@ -311,7 +311,7 @@ class LibraryPresenter( val filterFnStarted: (LibraryItem) -> Boolean = started@{ item -> if (filterStarted == State.IGNORE.value) return@started true - val hasStarted = item.manga.hasStarted + val hasStarted = item.libraryManga.hasStarted return@started if (filterStarted == State.INCLUDE.value) { hasStarted @@ -322,7 +322,7 @@ class LibraryPresenter( val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item -> if (filterCompleted == State.IGNORE.value) return@completed true - val isCompleted = item.manga.status == SManga.COMPLETED + val isCompleted = item.libraryManga.manga.status.toInt() == SManga.COMPLETED return@completed if (filterCompleted == State.INCLUDE.value) { isCompleted @@ -334,7 +334,7 @@ class LibraryPresenter( val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item -> if (isNotAnyLoggedIn) return@tracking true - val trackedManga = trackMap[item.manga.id ?: -1] + val trackedManga = trackMap[item.libraryManga.manga.id] val containsExclude = loggedInServices.filterValues { it == State.EXCLUDE.value } val containsInclude = loggedInServices.filterValues { it == State.INCLUDE.value } @@ -358,7 +358,7 @@ class LibraryPresenter( // SY --> val filterFnLewd: (LibraryItem) -> Boolean = lewd@{ item -> if (filterLewd == State.IGNORE.value) return@lewd true - val isLewd = item.manga.isLewd() + val isLewd = item.libraryManga.manga.isLewd() return@lewd if (filterLewd == State.INCLUDE.value) { isLewd @@ -416,14 +416,12 @@ class LibraryPresenter( for (item in itemList) { item.downloadCount = if (showDownloadBadges) { // SY --> - if (item.manga.source == MERGED_SOURCE_ID) { - item.manga.id?.let { mergeMangaId -> - runBlocking { - getMergedMangaById.await(mergeMangaId) - }.sumOf { downloadManager.getDownloadCount(it) } - } ?: 0 + if (item.libraryManga.manga.source == MERGED_SOURCE_ID) { + runBlocking { + getMergedMangaById.await(item.libraryManga.manga.id) + }.sumOf { downloadManager.getDownloadCount(it) }.toLong() } else { - /* SY <-- */ downloadManager.getDownloadCount(item.manga.toDomainManga()!!) + /* SY <-- */ downloadManager.getDownloadCount(item.libraryManga.manga).toLong() } } else { // Unset download count if not enabled @@ -431,21 +429,21 @@ class LibraryPresenter( } item.unreadCount = if (showUnreadBadges) { - item.manga.unreadCount + item.libraryManga.unreadCount } else { // Unset unread count if not enabled -1 } item.isLocal = if (showLocalBadges) { - item.manga.toDomainManga()!!.isLocal() + item.libraryManga.manga.isLocal() } else { // Hide / Unset local badge if not enabled false } item.sourceLanguage = if (showLanguageBadges) { - sourceManager.getOrStub(item.manga.source).lang.uppercase() + sourceManager.getOrStub(item.libraryManga.manga.source).lang.uppercase() } else { // Unset source language if not enabled "" @@ -519,51 +517,51 @@ class LibraryPresenter( val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 -> // SY --> val sort = when (groupType) { - LibraryGroup.BY_DEFAULT -> sortModes[i1.manga.category.toLong()]!! + LibraryGroup.BY_DEFAULT -> sortModes[i1.libraryManga.category]!! else -> groupSort } // SY <-- when (sort.type) { LibrarySort.Type.Alphabetical -> { - collator.compare(i1.manga.title.lowercase(locale), i2.manga.title.lowercase(locale)) + collator.compare(i1.libraryManga.manga.title.lowercase(locale), i2.libraryManga.manga.title.lowercase(locale)) } LibrarySort.Type.LastRead -> { - val manga1LastRead = lastReadManga[i1.manga.id!!] ?: 0 - val manga2LastRead = lastReadManga[i2.manga.id!!] ?: 0 + val manga1LastRead = lastReadManga[i1.libraryManga.manga.id] ?: 0 + val manga2LastRead = lastReadManga[i2.libraryManga.manga.id] ?: 0 manga1LastRead.compareTo(manga2LastRead) } LibrarySort.Type.LastUpdate -> { - i1.manga.last_update.compareTo(i2.manga.last_update) + i1.libraryManga.manga.lastUpdate.compareTo(i2.libraryManga.manga.lastUpdate) } LibrarySort.Type.UnreadCount -> when { // Ensure unread content comes first - i1.manga.unreadCount == i2.manga.unreadCount -> 0 - i1.manga.unreadCount == 0 -> if (sort.isAscending) 1 else -1 - i2.manga.unreadCount == 0 -> if (sort.isAscending) -1 else 1 - else -> i1.manga.unreadCount.compareTo(i2.manga.unreadCount) + i1.libraryManga.unreadCount == i2.libraryManga.unreadCount -> 0 + i1.libraryManga.unreadCount == 0L -> if (sort.isAscending) 1 else -1 + i2.libraryManga.unreadCount == 0L -> if (sort.isAscending) -1 else 1 + else -> i1.libraryManga.unreadCount.compareTo(i2.libraryManga.unreadCount) } LibrarySort.Type.TotalChapters -> { - i1.manga.totalChapters.compareTo(i2.manga.totalChapters) + i1.libraryManga.totalChapters.compareTo(i2.libraryManga.totalChapters) } LibrarySort.Type.LatestChapter -> { - val manga1latestChapter = latestChapterManga[i1.manga.id!!] + val manga1latestChapter = latestChapterManga[i1.libraryManga.manga.id] ?: latestChapterManga.size - val manga2latestChapter = latestChapterManga[i2.manga.id!!] + val manga2latestChapter = latestChapterManga[i2.libraryManga.manga.id] ?: latestChapterManga.size manga1latestChapter.compareTo(manga2latestChapter) } LibrarySort.Type.ChapterFetchDate -> { - val manga1chapterFetchDate = chapterFetchDateManga[i1.manga.id!!] ?: 0 - val manga2chapterFetchDate = chapterFetchDateManga[i2.manga.id!!] ?: 0 + val manga1chapterFetchDate = chapterFetchDateManga[i1.libraryManga.manga.id] ?: 0 + val manga2chapterFetchDate = chapterFetchDateManga[i2.libraryManga.manga.id] ?: 0 manga1chapterFetchDate.compareTo(manga2chapterFetchDate) } LibrarySort.Type.DateAdded -> { - i1.manga.date_added.compareTo(i2.manga.date_added) + i1.libraryManga.manga.dateAdded.compareTo(i1.libraryManga.manga.dateAdded) } // SY --> LibrarySort.Type.TagList -> { - val manga1IndexOfTag = listOfTags.indexOfFirst { i1.manga.getGenres()?.contains(it) ?: false } - val manga2IndexOfTag = listOfTags.indexOfFirst { i2.manga.getGenres()?.contains(it) ?: false } + val manga1IndexOfTag = listOfTags.indexOfFirst { i1.libraryManga.manga.genre?.contains(it) ?: false } + val manga2IndexOfTag = listOfTags.indexOfFirst { i2.libraryManga.manga.genre?.contains(it) ?: false } manga1IndexOfTag.compareTo(manga2IndexOfTag) } // SY <-- @@ -601,7 +599,7 @@ class LibraryPresenter( list.map { libraryManga -> // Display mode based on user preference: take it from global library setting or category LibraryItem(libraryManga) - }.groupBy { it.manga.category.toLong() } + }.groupBy { it.libraryManga.category.toLong() } } return combine(categoriesFlow, libraryMangasFlow) { dbCategories, libraryManga -> val categories = if (libraryManga.isNotEmpty() && libraryManga.containsKey(0).not()) { @@ -626,13 +624,13 @@ class LibraryPresenter( LibraryGroup.UNGROUPED -> { editedCategories = listOf(Category(0, "All", 0, 0)) mapOf( - 0L to map.values.flatten().distinctBy { it.manga.id }, + 0L to map.values.flatten().distinctBy { it.libraryManga.manga.id }, ) } else -> { val (items, customCategories) = getGroupedMangaItems( groupType = groupType, - libraryManga = map.values.flatten().distinctBy { it.manga.id }, + libraryManga = map.values.flatten().distinctBy { it.libraryManga.manga.id }, ) editedCategories = customCategories items @@ -782,8 +780,8 @@ class LibraryPresenter( } // SY --> - fun cleanTitles(mangas: List) { - mangas.forEach { manga -> + fun cleanTitles(mangas: List) { + mangas.forEach { (manga) -> val editedTitle = manga.title.replace("\\[.*?]".toRegex(), "").trim().replace("\\(.*?\\)".toRegex(), "").trim().replace("\\{.*?\\}".toRegex(), "").trim().let { if (it.contains("|")) { it.replace(".*\\|".toRegex(), "").trim() @@ -795,22 +793,22 @@ class LibraryPresenter( val mangaJson = CustomMangaManager.MangaJson( id = manga.id, title = editedTitle.nullIfBlank(), - author = manga.author.takeUnless { it == manga.originalAuthor }, - artist = manga.artist.takeUnless { it == manga.originalArtist }, - description = manga.description.takeUnless { it == manga.originalDescription }, - genre = manga.getGenres().takeUnless { it == manga.getOriginalGenres() }, - status = manga.status.takeUnless { it == manga.originalStatus }?.toLong(), + author = manga.author.takeUnless { it == manga.ogAuthor }, + artist = manga.artist.takeUnless { it == manga.ogArtist }, + description = manga.description.takeUnless { it == manga.ogDescription }, + genre = manga.genre.takeUnless { it == manga.ogGenre }, + status = manga.status.takeUnless { it == manga.ogStatus }?.toLong(), ) customMangaManager.saveMangaInfo(mangaJson) } } - fun syncMangaToDex(mangaList: List) { + fun syncMangaToDex(mangaList: List) { launchIO { MdUtil.getEnabledMangaDex(unsortedPreferences, sourcePreferences, sourceManager)?.let { mdex -> - mangaList.forEach { - mdex.updateFollowStatus(MdUtil.getMangaId(it.url), FollowStatus.READING) + mangaList.forEach { (manga) -> + mdex.updateFollowStatus(MdUtil.getMangaId(manga.url), FollowStatus.READING) } } } @@ -927,7 +925,7 @@ class LibraryPresenter( val count = when { category == null || mangaCountVisibility.not() -> null tabVisibility.not() -> loadedManga[category.id]?.size - else -> loadedManga.values.flatten().distinctBy { it.manga.id }.size + else -> loadedManga.values.flatten().distinctBy { it.libraryManga.manga.id }.size } value = when (category) { @@ -983,23 +981,23 @@ class LibraryPresenter( val parsedQuery = searchEngine.parseQuery(query) val mangaWithMetaIds = getIdsOfFavoriteMangaWithMetadata.await() val tracks = if (loggedServices.isNotEmpty()) { - getTracks.await(unfiltered.mapNotNull { it.manga.id }.distinct()) + getTracks.await(unfiltered.map { it.libraryManga.manga.id }.distinct()) } else { emptyMap() } val sources = unfiltered - .distinctBy { it.manga.source } - .mapNotNull { sourceManager.get(it.manga.source) } + .distinctBy { it.libraryManga.manga.source } + .mapNotNull { sourceManager.get(it.libraryManga.manga.source) } .associateBy { it.id } unfiltered.asFlow().cancellable().filter { item -> - val mangaId = item.manga.id ?: -1 - val sourceId = item.manga.source + val mangaId = item.libraryManga.manga.id + val sourceId = item.libraryManga.manga.source if (isMetadataSource(sourceId)) { if (mangaWithMetaIds.binarySearch(mangaId) < 0) { // No meta? Filter using title filterManga( queries = parsedQuery, - manga = item.manga, + libraryManga = item.libraryManga, tracks = tracks[mangaId], source = sources[sourceId], ) @@ -1008,7 +1006,7 @@ class LibraryPresenter( val titles = getSearchTitles.await(mangaId) filterManga( queries = parsedQuery, - manga = item.manga, + libraryManga = item.libraryManga, tracks = tracks[mangaId], source = sources[sourceId], checkGenre = false, @@ -1019,7 +1017,7 @@ class LibraryPresenter( } else { filterManga( queries = parsedQuery, - manga = item.manga, + libraryManga = item.libraryManga, tracks = tracks[mangaId], source = sources[sourceId], ) @@ -1036,15 +1034,16 @@ class LibraryPresenter( private fun filterManga( queries: List, - manga: LibraryManga, + libraryManga: LibraryManga, tracks: List?, source: Source?, checkGenre: Boolean = true, searchTags: List? = null, searchTitles: List? = null, ): Boolean { + val manga = libraryManga.manga val sourceIdString = manga.source.takeUnless { it == LocalSource.ID }?.toString() - val genre = if (checkGenre) manga.getGenres().orEmpty() else emptyList() + val genre = if (checkGenre) manga.genre.orEmpty() else emptyList() return queries.all { queryComponent -> when (queryComponent.excluded) { false -> when (queryComponent) { @@ -1142,7 +1141,7 @@ class LibraryPresenter( fun toggleSelection(manga: LibraryManga) { val mutableList = state.selection.toMutableList() - if (selection.fastAny { it.id == manga.id }) { + if (selection.fastAny { it.manga.id == manga.manga.id }) { mutableList.remove(manga) } else { mutableList.add(manga) @@ -1154,13 +1153,13 @@ class LibraryPresenter( val category = categories[index] val items = loadedManga[category.id] ?: emptyList() state.selection = state.selection.toMutableList().apply { - addAll(items.filterNot { it.manga in selection }.map { it.manga }) + addAll(items.filterNot { it.libraryManga in selection }.map { it.libraryManga }) } } fun invertSelection(index: Int) { val category = categories[index] - val items = (loadedManga[category.id] ?: emptyList()).map { it.manga } + val items = (loadedManga[category.id] ?: emptyList()).map { it.libraryManga } state.selection = items.filterNot { it in selection } } @@ -1189,8 +1188,8 @@ class LibraryPresenter( val manga = when (groupType) { LibraryGroup.BY_TRACK_STATUS -> { val tracks = runBlocking { getTracks.await() }.groupBy { it.mangaId } - libraryManga.groupBy { libraryItem -> - val status = tracks[libraryItem.manga.id]?.firstNotNullOfOrNull { track -> + libraryManga.groupBy { item -> + val status = tracks[item.libraryManga.manga.id]?.firstNotNullOfOrNull { track -> TrackStatus.parseTrackerStatus(track.syncId, track.status) } ?: TrackStatus.OTHER @@ -1198,14 +1197,14 @@ class LibraryPresenter( }.mapKeys { it.key.toLong() } } LibraryGroup.BY_SOURCE -> { - libraryManga.groupBy { libraryItem -> - libraryItem.manga.source + libraryManga.groupBy { item -> + item.libraryManga.manga.source } } else -> { - libraryManga.groupBy { libraryItem -> - libraryItem.manga.status - }.mapKeys { it.key.toLong() } + libraryManga.groupBy { item -> + item.libraryManga.manga.status + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt index c0e5f93e6..6c196e72a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt @@ -20,26 +20,26 @@ import eu.kanade.domain.manga.model.Manga as DomainManga /** * Call before updating [Manga.thumbnail_url] to ensure old cover can be cleared from cache */ -fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSameUrl: Boolean) { +fun DomainManga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSameUrl: Boolean): DomainManga { // Never refresh covers if the new url is null, as the current url has possibly become invalid - val newUrl = remoteManga.thumbnail_url ?: return + val newUrl = remoteManga.thumbnail_url ?: return this // Never refresh covers if the url is empty to avoid "losing" existing covers - if (newUrl.isEmpty()) return + if (newUrl.isEmpty()) return this - if (!refreshSameUrl && thumbnail_url == newUrl) return + if (!refreshSameUrl && thumbnailUrl == newUrl) return this - val domainManga = toDomainManga()!! - when { - domainManga.isLocal() -> { - cover_last_modified = Date().time + return when { + isLocal() -> { + this.copy(coverLastModified = Date().time) } - domainManga.hasCustomCover(coverCache) -> { + hasCustomCover(coverCache) -> { coverCache.deleteFromCache(this, false) + this } else -> { - cover_last_modified = Date().time coverCache.deleteFromCache(this, false) + this.copy(coverLastModified = Date().time) } } } diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index a73527ec0..e0e830fb8 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -15,7 +15,6 @@ import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.Manga import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.source.SourceManager @@ -98,17 +97,17 @@ class FavoritesSyncHelper(val context: Context) { status.value = FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_verifying_library), context = context) val libraryManga = getLibraryManga.await() val seenManga = HashSet(libraryManga.size) - libraryManga.forEach { - if (!it.isEhBasedManga()) return@forEach + libraryManga.forEach { (manga) -> + if (!manga.isEhBasedManga()) return@forEach - if (it.id in seenManga) { - val inCategories = getCategories.await(it.id!!) - status.value = FavoritesSyncStatus.BadLibraryState.MangaInMultipleCategories(it.toDomainManga()!!, inCategories, context) + if (manga.id in seenManga) { + val inCategories = getCategories.await(manga.id) + status.value = FavoritesSyncStatus.BadLibraryState.MangaInMultipleCategories(manga, inCategories, context) - logger.w(context.getString(R.string.favorites_sync_manga_multiple_categories_error, it.id)) + logger.w(context.getString(R.string.favorites_sync_manga_multiple_categories_error, manga.id)) return } else { - seenManga += it.id!! + seenManga += manga.id } } diff --git a/app/src/main/java/exh/util/LewdMangaChecker.kt b/app/src/main/java/exh/util/LewdMangaChecker.kt index c675ef24f..5b9eceb3c 100644 --- a/app/src/main/java/exh/util/LewdMangaChecker.kt +++ b/app/src/main/java/exh/util/LewdMangaChecker.kt @@ -1,6 +1,6 @@ package exh.util -import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.domain.manga.model.Manga import eu.kanade.tachiyomi.source.SourceManager import exh.source.isEhBasedManga import exh.source.nHentaiSourceIds @@ -9,15 +9,14 @@ import uy.kohesive.injekt.api.get fun Manga.isLewd(): Boolean { val sourceName = Injekt.get().get(source)?.name - val currentTags = getGenres().orEmpty() if (isEhBasedManga() || source in nHentaiSourceIds) { - return currentTags.none { tag -> isNonHentaiTag(tag) } + return genre.orEmpty().none { tag -> isNonHentaiTag(tag) } } return source in 6905L..6913L || (sourceName != null && isHentaiSource(sourceName)) || - currentTags.any { tag -> isHentaiTag(tag) } + genre.orEmpty().any { tag -> isHentaiTag(tag) } } private fun isNonHentaiTag(tag: String): Boolean {