Allow user to read all read manga stats
This commit is contained in:
parent
197f729023
commit
e9a3463455
@ -43,6 +43,7 @@ import tachiyomi.domain.manga.interactor.GetMergedManga
|
|||||||
import tachiyomi.domain.manga.interactor.GetMergedMangaById
|
import tachiyomi.domain.manga.interactor.GetMergedMangaById
|
||||||
import tachiyomi.domain.manga.interactor.GetMergedMangaForDownloading
|
import tachiyomi.domain.manga.interactor.GetMergedMangaForDownloading
|
||||||
import tachiyomi.domain.manga.interactor.GetMergedReferencesById
|
import tachiyomi.domain.manga.interactor.GetMergedReferencesById
|
||||||
|
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchMetadata
|
import tachiyomi.domain.manga.interactor.GetSearchMetadata
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchTags
|
import tachiyomi.domain.manga.interactor.GetSearchTags
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchTitles
|
import tachiyomi.domain.manga.interactor.GetSearchTitles
|
||||||
@ -108,6 +109,7 @@ class SYDomainModule : InjektModule {
|
|||||||
addFactory { GetPagePreviews(get(), get()) }
|
addFactory { GetPagePreviews(get(), get()) }
|
||||||
addFactory { SearchEngine() }
|
addFactory { SearchEngine() }
|
||||||
addFactory { IsTrackUnfollowed() }
|
addFactory { IsTrackUnfollowed() }
|
||||||
|
addFactory { GetReadMangaNotInLibrary(get()) }
|
||||||
|
|
||||||
// Required for [MetadataSource]
|
// Required for [MetadataSource]
|
||||||
addFactory<MetadataSource.GetMangaId> { GetManga(get()) }
|
addFactory<MetadataSource.GetMangaId> { GetManga(get()) }
|
||||||
|
@ -8,6 +8,7 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
|
|||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import eu.kanade.presentation.components.AppBar
|
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.StatsScreenContent
|
||||||
import eu.kanade.presentation.more.stats.StatsScreenState
|
import eu.kanade.presentation.more.stats.StatsScreenState
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
@ -35,11 +36,28 @@ class StatsScreen : Screen() {
|
|||||||
title = stringResource(R.string.label_stats),
|
title = stringResource(R.string.label_stats),
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
scrollBehavior = scrollBehavior,
|
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 ->
|
) { paddingValues ->
|
||||||
StatsScreenContent(
|
StatsScreenContent(
|
||||||
state = state as StatsScreenState.Success,
|
state = state as? StatsScreenState.Success ?: return@Scaffold,
|
||||||
paddingValues = paddingValues,
|
paddingValues = paddingValues,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,11 @@ import eu.kanade.presentation.more.stats.data.StatsData
|
|||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
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 kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.core.util.lang.launchIO
|
|
||||||
import tachiyomi.domain.history.interactor.GetTotalReadDuration
|
import tachiyomi.domain.history.interactor.GetTotalReadDuration
|
||||||
import tachiyomi.domain.library.model.LibraryManga
|
import tachiyomi.domain.library.model.LibraryManga
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
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_COMPLETED
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
||||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||||
|
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
import tachiyomi.source.local.isLocal
|
import tachiyomi.source.local.isLocal
|
||||||
@ -34,13 +38,28 @@ class StatsScreenModel(
|
|||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val preferences: LibraryPreferences = Injekt.get(),
|
private val preferences: LibraryPreferences = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackManager: TrackManager = Injekt.get(),
|
||||||
|
// SY -->
|
||||||
|
private val getReadMangaNotInLibrary: GetReadMangaNotInLibrary = Injekt.get(),
|
||||||
|
// SY <--
|
||||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||||
|
|
||||||
private val loggedServices by lazy { trackManager.services.fastFilter { it.isLogged } }
|
private val loggedServices by lazy { trackManager.services.fastFilter { it.isLogged } }
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
private val _allRead = MutableStateFlow(false)
|
||||||
|
val allRead = _allRead.asStateFlow()
|
||||||
|
// SY <--
|
||||||
|
|
||||||
init {
|
init {
|
||||||
coroutineScope.launchIO {
|
// SY -->
|
||||||
val libraryManga = getLibraryManga.await()
|
_allRead.onEach { allRead ->
|
||||||
|
mutableState.update { StatsScreenState.Loading }
|
||||||
|
val libraryManga = getLibraryManga.await() + if (allRead) {
|
||||||
|
getReadMangaNotInLibrary.await()
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
val distinctLibraryManga = libraryManga.fastDistinctBy { it.id }
|
val distinctLibraryManga = libraryManga.fastDistinctBy { it.id }
|
||||||
|
|
||||||
@ -83,7 +102,9 @@ class StatsScreenModel(
|
|||||||
trackers = trackersStatData,
|
trackers = trackersStatData,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
// SY -->
|
||||||
|
}.launchIn(coroutineScope)
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGlobalUpdateItemCount(libraryManga: List<LibraryManga>): Int {
|
private fun getGlobalUpdateItemCount(libraryManga: List<LibraryManga>): Int {
|
||||||
@ -149,4 +170,8 @@ class StatsScreenModel(
|
|||||||
val service = trackManager.getService(track.syncId)!!
|
val service = trackManager.getService(track.syncId)!!
|
||||||
return service.get10PointScore(track)
|
return service.get10PointScore(track)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toggleReadManga() {
|
||||||
|
_allRead.value = !_allRead.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ class AndroidDatabaseHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
fun getLibraryQuery() = LibraryQuery(driver)
|
fun getLibraryQuery(condition: String = "M.favorite = 1") = LibraryQuery(driver, condition)
|
||||||
|
|
||||||
fun getUpdatesQuery(after: Long) = UpdatesQuery(driver, after)
|
fun getUpdatesQuery(after: Long) = UpdatesQuery(driver, after)
|
||||||
// SY <--
|
// SY <--
|
||||||
|
@ -40,7 +40,10 @@ private val mapper = { cursor: SqlCursor ->
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibraryQuery(val driver: SqlDriver) : Query<LibraryView>(copyOnWriteList(), mapper) {
|
class LibraryQuery(
|
||||||
|
val driver: SqlDriver,
|
||||||
|
val condition: String = "M.favorite = 1",
|
||||||
|
) : Query<LibraryView>(copyOnWriteList(), mapper) {
|
||||||
override fun execute(): SqlCursor {
|
override fun execute(): SqlCursor {
|
||||||
return driver.executeQuery(
|
return driver.executeQuery(
|
||||||
null,
|
null,
|
||||||
@ -72,7 +75,7 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryView>(copyOnWriteList()
|
|||||||
ON M._id = C.manga_id
|
ON M._id = C.manga_id
|
||||||
LEFT JOIN mangas_categories AS MC
|
LEFT JOIN mangas_categories AS MC
|
||||||
ON MC.manga_id = M._id
|
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
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
M.*,
|
M.*,
|
||||||
@ -109,7 +112,7 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryView>(copyOnWriteList()
|
|||||||
ON ME.merge_id = C.merge_id
|
ON ME.merge_id = C.merge_id
|
||||||
LEFT JOIN mangas_categories AS MC
|
LEFT JOIN mangas_categories AS MC
|
||||||
ON MC.manga_id = M._id
|
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(),
|
""".trimIndent(),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
@ -179,5 +179,11 @@ class MangaRepositoryImpl(
|
|||||||
override suspend fun deleteManga(mangaId: Long) {
|
override suspend fun deleteManga(mangaId: Long) {
|
||||||
handler.await { mangasQueries.deleteById(mangaId) }
|
handler.await { mangasQueries.deleteById(mangaId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getReadMangaNotInLibrary(): List<LibraryManga> {
|
||||||
|
return handler.awaitList {
|
||||||
|
(handler as AndroidDatabaseHandler).getLibraryQuery("M.favorite = 0 AND C.readCount != 0")
|
||||||
|
}.map(libraryViewMapper)
|
||||||
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -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<LibraryManga> {
|
||||||
|
return mangaRepository.getReadMangaNotInLibrary()
|
||||||
|
}
|
||||||
|
}
|
@ -41,5 +41,7 @@ interface MangaRepository {
|
|||||||
suspend fun getAll(): List<Manga>
|
suspend fun getAll(): List<Manga>
|
||||||
|
|
||||||
suspend fun deleteManga(mangaId: Long)
|
suspend fun deleteManga(mangaId: Long)
|
||||||
|
|
||||||
|
suspend fun getReadMangaNotInLibrary(): List<LibraryManga>
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -709,6 +709,10 @@
|
|||||||
<string name="relation_serialization">Serialization</string>
|
<string name="relation_serialization">Serialization</string>
|
||||||
<string name="relation_alternate_version">Alternate version</string>
|
<string name="relation_alternate_version">Alternate version</string>
|
||||||
|
|
||||||
|
<!-- Stats page -->
|
||||||
|
<string name="include_all_read_entries">Include all read entries</string>
|
||||||
|
<string name="ignore_non_library_entries">Ignore non-library entries</string>
|
||||||
|
|
||||||
<!-- Humanize time -->
|
<!-- Humanize time -->
|
||||||
<plurals name="humanize_year">
|
<plurals name="humanize_year">
|
||||||
<item quantity="one">%1$d year ago</item>
|
<item quantity="one">%1$d year ago</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user