diff --git a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt index 46012afa9..394641fef 100644 --- a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt @@ -43,6 +43,7 @@ import tachiyomi.domain.manga.interactor.GetMergedManga import tachiyomi.domain.manga.interactor.GetMergedMangaById import tachiyomi.domain.manga.interactor.GetMergedMangaForDownloading import tachiyomi.domain.manga.interactor.GetMergedReferencesById +import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary import tachiyomi.domain.manga.interactor.GetSearchMetadata import tachiyomi.domain.manga.interactor.GetSearchTags import tachiyomi.domain.manga.interactor.GetSearchTitles @@ -108,6 +109,7 @@ class SYDomainModule : InjektModule { addFactory { GetPagePreviews(get(), get()) } addFactory { SearchEngine() } addFactory { IsTrackUnfollowed() } + addFactory { GetReadMangaNotInLibrary(get()) } // Required for [MetadataSource] addFactory { GetManga(get()) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt index a76f83783..00c872916 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt @@ -8,6 +8,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.AppBar +import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.more.stats.StatsScreenContent import eu.kanade.presentation.more.stats.StatsScreenState import eu.kanade.presentation.util.Screen @@ -35,11 +36,28 @@ class StatsScreen : Screen() { title = stringResource(R.string.label_stats), navigateUp = navigator::pop, scrollBehavior = scrollBehavior, + // SY --> + actions = { + val allRead by screenModel.allRead.collectAsState() + AppBarActions( + listOf( + AppBar.OverflowAction( + title = if (allRead) { + stringResource(R.string.ignore_non_library_entries) + } else { + stringResource(R.string.include_all_read_entries) + }, + onClick = screenModel::toggleReadManga, + ), + ), + ) + }, + // SY <-- ) }, ) { paddingValues -> StatsScreenContent( - state = state as StatsScreenState.Success, + state = state as? StatsScreenState.Success ?: return@Scaffold, paddingValues = paddingValues, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt index 366486a0d..73b8ab8cd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt @@ -12,8 +12,11 @@ import eu.kanade.presentation.more.stats.data.StatsData import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.model.SManga +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import tachiyomi.core.util.lang.launchIO import tachiyomi.domain.history.interactor.GetTotalReadDuration import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.library.service.LibraryPreferences @@ -21,6 +24,7 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_U import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ import tachiyomi.domain.manga.interactor.GetLibraryManga +import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.model.Track import tachiyomi.source.local.isLocal @@ -34,13 +38,28 @@ class StatsScreenModel( private val getTracks: GetTracks = Injekt.get(), private val preferences: LibraryPreferences = Injekt.get(), private val trackManager: TrackManager = Injekt.get(), + // SY --> + private val getReadMangaNotInLibrary: GetReadMangaNotInLibrary = Injekt.get(), + // SY <-- ) : StateScreenModel(StatsScreenState.Loading) { private val loggedServices by lazy { trackManager.services.fastFilter { it.isLogged } } + // SY --> + private val _allRead = MutableStateFlow(false) + val allRead = _allRead.asStateFlow() + // SY <-- + init { - coroutineScope.launchIO { - val libraryManga = getLibraryManga.await() + // SY --> + _allRead.onEach { allRead -> + mutableState.update { StatsScreenState.Loading } + val libraryManga = getLibraryManga.await() + if (allRead) { + getReadMangaNotInLibrary.await() + } else { + emptyList() + } + // SY <-- val distinctLibraryManga = libraryManga.fastDistinctBy { it.id } @@ -83,7 +102,9 @@ class StatsScreenModel( trackers = trackersStatData, ) } - } + // SY --> + }.launchIn(coroutineScope) + // SY <-- } private fun getGlobalUpdateItemCount(libraryManga: List): Int { @@ -149,4 +170,8 @@ class StatsScreenModel( val service = trackManager.getService(track.syncId)!! return service.get10PointScore(track) } + + fun toggleReadManga() { + _allRead.value = !_allRead.value + } } diff --git a/data/src/main/java/tachiyomi/data/AndroidDatabaseHandler.kt b/data/src/main/java/tachiyomi/data/AndroidDatabaseHandler.kt index e0f45a215..0089960fe 100644 --- a/data/src/main/java/tachiyomi/data/AndroidDatabaseHandler.kt +++ b/data/src/main/java/tachiyomi/data/AndroidDatabaseHandler.kt @@ -88,7 +88,7 @@ class AndroidDatabaseHandler( } // SY --> - fun getLibraryQuery() = LibraryQuery(driver) + fun getLibraryQuery(condition: String = "M.favorite = 1") = LibraryQuery(driver, condition) fun getUpdatesQuery(after: Long) = UpdatesQuery(driver, after) // SY <-- diff --git a/data/src/main/java/tachiyomi/data/LibraryQuery.kt b/data/src/main/java/tachiyomi/data/LibraryQuery.kt index 3e38cc63e..eeb8a2396 100644 --- a/data/src/main/java/tachiyomi/data/LibraryQuery.kt +++ b/data/src/main/java/tachiyomi/data/LibraryQuery.kt @@ -40,7 +40,10 @@ private val mapper = { cursor: SqlCursor -> ) } -class LibraryQuery(val driver: SqlDriver) : Query(copyOnWriteList(), mapper) { +class LibraryQuery( + val driver: SqlDriver, + val condition: String = "M.favorite = 1", +) : Query(copyOnWriteList(), mapper) { override fun execute(): SqlCursor { return driver.executeQuery( null, @@ -72,7 +75,7 @@ class LibraryQuery(val driver: SqlDriver) : Query(copyOnWriteList() ON M._id = C.manga_id LEFT JOIN mangas_categories AS MC ON MC.manga_id = M._id - WHERE M.favorite = 1 AND M.source <> $MERGED_SOURCE_ID + WHERE $condition AND M.source <> $MERGED_SOURCE_ID UNION SELECT M.*, @@ -109,7 +112,7 @@ class LibraryQuery(val driver: SqlDriver) : Query(copyOnWriteList() ON ME.merge_id = C.merge_id LEFT JOIN mangas_categories AS MC ON MC.manga_id = M._id - WHERE M.favorite = 1 AND M.source = $MERGED_SOURCE_ID; + WHERE $condition AND M.source = $MERGED_SOURCE_ID; """.trimIndent(), 1, ) diff --git a/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt b/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt index b21502335..0fc896b70 100644 --- a/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt +++ b/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt @@ -179,5 +179,11 @@ class MangaRepositoryImpl( override suspend fun deleteManga(mangaId: Long) { handler.await { mangasQueries.deleteById(mangaId) } } + + override suspend fun getReadMangaNotInLibrary(): List { + return handler.awaitList { + (handler as AndroidDatabaseHandler).getLibraryQuery("M.favorite = 0 AND C.readCount != 0") + }.map(libraryViewMapper) + } // SY <-- } diff --git a/domain/src/main/java/tachiyomi/domain/manga/interactor/GetReadMangaNotInLibrary.kt b/domain/src/main/java/tachiyomi/domain/manga/interactor/GetReadMangaNotInLibrary.kt new file mode 100644 index 000000000..57cc6c5cb --- /dev/null +++ b/domain/src/main/java/tachiyomi/domain/manga/interactor/GetReadMangaNotInLibrary.kt @@ -0,0 +1,13 @@ +package tachiyomi.domain.manga.interactor + +import tachiyomi.domain.library.model.LibraryManga +import tachiyomi.domain.manga.repository.MangaRepository + +class GetReadMangaNotInLibrary( + private val mangaRepository: MangaRepository, +) { + + suspend fun await(): List { + return mangaRepository.getReadMangaNotInLibrary() + } +} diff --git a/domain/src/main/java/tachiyomi/domain/manga/repository/MangaRepository.kt b/domain/src/main/java/tachiyomi/domain/manga/repository/MangaRepository.kt index 77b085cea..8709158ac 100644 --- a/domain/src/main/java/tachiyomi/domain/manga/repository/MangaRepository.kt +++ b/domain/src/main/java/tachiyomi/domain/manga/repository/MangaRepository.kt @@ -41,5 +41,7 @@ interface MangaRepository { suspend fun getAll(): List suspend fun deleteManga(mangaId: Long) + + suspend fun getReadMangaNotInLibrary(): List // SY <-- } diff --git a/i18n/src/main/res/values/strings_sy.xml b/i18n/src/main/res/values/strings_sy.xml index 4797d379a..5f88a954d 100644 --- a/i18n/src/main/res/values/strings_sy.xml +++ b/i18n/src/main/res/values/strings_sy.xml @@ -709,6 +709,10 @@ Serialization Alternate version + + Include all read entries + Ignore non-library entries + %1$d year ago