Added library sort by mean Tracker score (#10005)
(cherry picked from commit 5d91b77c9340604436c63073c83ad8b37794ddf0) # Conflicts: # app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt # domain/src/main/java/tachiyomi/domain/library/model/LibrarySortMode.kt # domain/src/main/java/tachiyomi/domain/track/interactor/GetTracksPerManga.kt
This commit is contained in:
parent
43c5585f7e
commit
e14cc134a0
@ -185,6 +185,13 @@ private fun ColumnScope.SortPage(
|
||||
}.collectAsState(initial = screenModel.libraryPreferences.sortTagsForLibrary().get().isNotEmpty())
|
||||
// SY <--
|
||||
|
||||
val trackerSortOption =
|
||||
if (screenModel.trackers.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOf(R.string.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
|
||||
}
|
||||
|
||||
listOfNotNull(
|
||||
R.string.action_sort_alpha to LibrarySort.Type.Alphabetical,
|
||||
R.string.action_sort_total to LibrarySort.Type.TotalChapters,
|
||||
@ -194,12 +201,14 @@ private fun ColumnScope.SortPage(
|
||||
R.string.action_sort_latest_chapter to LibrarySort.Type.LatestChapter,
|
||||
R.string.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate,
|
||||
R.string.action_sort_date_added to LibrarySort.Type.DateAdded,
|
||||
// SY -->
|
||||
if (hasSortTags) {
|
||||
R.string.tag_sorting to LibrarySort.Type.TagList
|
||||
} else {
|
||||
null
|
||||
},
|
||||
).map { (titleRes, mode) ->
|
||||
// SY <--
|
||||
).plus(trackerSortOption).map { (titleRes, mode) ->
|
||||
SortItem(
|
||||
label = stringResource(titleRes),
|
||||
sortDescending = sortDescending.takeIf { sortingMode == mode },
|
||||
@ -290,6 +299,7 @@ private fun ColumnScope.DisplayPage(
|
||||
)
|
||||
}
|
||||
|
||||
// SY -->
|
||||
data class GroupMode(
|
||||
val int: Int,
|
||||
val nameRes: Int,
|
||||
@ -342,3 +352,4 @@ private fun ColumnScope.GroupPage(
|
||||
)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
@ -37,6 +37,8 @@ class TrackerManager {
|
||||
|
||||
val trackers = listOf(mdList, myAnimeList, aniList, kitsu, shikimori, bangumi, komga, mangaUpdates, kavita, suwayomi)
|
||||
|
||||
fun loggedInTrackers() = trackers.filter { it.isLoggedIn }
|
||||
|
||||
fun get(id: Long) = trackers.find { it.id == id }
|
||||
|
||||
fun hasLoggedIn() = trackers.any { it.isLoggedIn }
|
||||
|
@ -176,7 +176,7 @@ class LibraryScreenModel(
|
||||
.applyGrouping(groupType)
|
||||
// SY <--
|
||||
.applyFilters(tracks, loggedInTrackers)
|
||||
.applySort(/* SY --> */sort.takeIf { groupType != LibraryGroup.BY_DEFAULT } /* SY <-- */)
|
||||
.applySort(tracks, /* SY --> */sort.takeIf { groupType != LibraryGroup.BY_DEFAULT } /* SY <-- */)
|
||||
.mapValues { (_, value) ->
|
||||
if (searchQuery != null) {
|
||||
// Filter query
|
||||
@ -267,7 +267,7 @@ class LibraryScreenModel(
|
||||
* Applies library filters to the given map of manga.
|
||||
*/
|
||||
private suspend fun LibraryMap.applyFilters(
|
||||
trackMap: Map<Long, List<Long>>,
|
||||
trackMap: Map<Long, List<Track>>,
|
||||
loggedInTrackers: Map<Long, TriState>,
|
||||
): LibraryMap {
|
||||
val prefs = getLibraryItemPreferencesFlow().first()
|
||||
@ -322,7 +322,9 @@ class LibraryScreenModel(
|
||||
val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item ->
|
||||
if (isNotLoggedInAnyTrack || trackFiltersIsIgnored) return@tracking true
|
||||
|
||||
val mangaTracks = trackMap[item.libraryManga.id].orEmpty()
|
||||
val mangaTracks = trackMap
|
||||
.mapValues { entry -> entry.value.map { it.syncId } }[item.libraryManga.id]
|
||||
.orEmpty()
|
||||
|
||||
val isExcluded = excludedTracks.isNotEmpty() && mangaTracks.fastAny { it in excludedTracks }
|
||||
val isIncluded = includedTracks.isEmpty() || mangaTracks.fastAny { it in includedTracks }
|
||||
@ -348,7 +350,11 @@ class LibraryScreenModel(
|
||||
/**
|
||||
* Applies library sorting to the given map of manga.
|
||||
*/
|
||||
private fun LibraryMap.applySort(/* SY --> */ groupSort: LibrarySort? = null /* SY <-- */): LibraryMap {
|
||||
private fun LibraryMap.applySort(
|
||||
// Map<MangaId, List<Track>>
|
||||
trackMap: Map<Long, List<Track>>,
|
||||
/* SY --> */ groupSort: LibrarySort? = null, /* SY <-- */
|
||||
): LibraryMap {
|
||||
// SY -->
|
||||
val listOfTags by lazy {
|
||||
libraryPreferences.sortTagsForLibrary().get()
|
||||
@ -371,6 +377,20 @@ class LibraryScreenModel(
|
||||
collator.compare(i1.libraryManga.manga.title.lowercase(locale), i2.libraryManga.manga.title.lowercase(locale))
|
||||
}
|
||||
|
||||
val defaultTrackerScoreSortValue = -1.0
|
||||
val trackerScores by lazy {
|
||||
val trackerMap = trackerManager.loggedInTrackers().associateBy { e -> e.id }
|
||||
trackMap.mapValues { entry ->
|
||||
when {
|
||||
entry.value.isEmpty() -> null
|
||||
else ->
|
||||
entry.value
|
||||
.mapNotNull { trackerMap[it.syncId]?.get10PointScore(it) }
|
||||
.average()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
|
||||
// SY -->
|
||||
val sort = groupSort ?: keys.find { it.id == i1.libraryManga.category }!!.sort
|
||||
@ -404,6 +424,11 @@ class LibraryScreenModel(
|
||||
LibrarySort.Type.DateAdded -> {
|
||||
i1.libraryManga.manga.dateAdded.compareTo(i2.libraryManga.manga.dateAdded)
|
||||
}
|
||||
LibrarySort.Type.TrackerMean -> {
|
||||
val item1Score = trackerScores[i1.libraryManga.id] ?: defaultTrackerScoreSortValue
|
||||
val item2Score = trackerScores[i2.libraryManga.id] ?: defaultTrackerScoreSortValue
|
||||
item1Score.compareTo(item2Score)
|
||||
}
|
||||
// SY -->
|
||||
LibrarySort.Type.TagList -> {
|
||||
val manga1IndexOfTag = listOfTags.indexOfFirst { i1.libraryManga.manga.genre?.contains(it) ?: false }
|
||||
@ -550,7 +575,7 @@ class LibraryScreenModel(
|
||||
* @return map of track id with the filter value
|
||||
*/
|
||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||
val loggedInTrackers = trackerManager.trackers.filter { it.isLoggedIn }
|
||||
val loggedInTrackers = trackerManager.loggedInTrackers()
|
||||
return if (loggedInTrackers.isNotEmpty()) {
|
||||
val prefFlows = loggedInTrackers
|
||||
.map { libraryPreferences.filterTracking(it.id.toInt()).changes() }
|
||||
|
@ -30,9 +30,10 @@ data class LibrarySort(
|
||||
data object LatestChapter : Type(0b00010100)
|
||||
data object ChapterFetchDate : Type(0b00011000)
|
||||
data object DateAdded : Type(0b00011100)
|
||||
data object TrackerMean : Type(0b000100000)
|
||||
|
||||
// SY -->
|
||||
object TagList : Type(0b00100100)
|
||||
data object TagList : Type(0b00100100)
|
||||
// SY <--
|
||||
|
||||
companion object {
|
||||
@ -79,6 +80,7 @@ data class LibrarySort(
|
||||
Type.LatestChapter,
|
||||
Type.ChapterFetchDate,
|
||||
Type.DateAdded,
|
||||
Type.TrackerMean,
|
||||
/* SY -->*/ Type.TagList, /* SY <--*/
|
||||
)
|
||||
}
|
||||
@ -106,6 +108,7 @@ data class LibrarySort(
|
||||
"LATEST_CHAPTER" -> Type.LatestChapter
|
||||
"CHAPTER_FETCH_DATE" -> Type.ChapterFetchDate
|
||||
"DATE_ADDED" -> Type.DateAdded
|
||||
"TRACKER_MEAN" -> Type.TrackerMean
|
||||
// SY -->
|
||||
"TAG_LIST" -> Type.TagList
|
||||
// SY <--
|
||||
@ -129,7 +132,10 @@ data class LibrarySort(
|
||||
Type.LatestChapter -> "LATEST_CHAPTER"
|
||||
Type.ChapterFetchDate -> "CHAPTER_FETCH_DATE"
|
||||
Type.DateAdded -> "DATE_ADDED"
|
||||
Type.TrackerMean -> "TRACKER_MEAN"
|
||||
// SY -->
|
||||
Type.TagList -> "TAG_LIST"
|
||||
// SY <--
|
||||
}
|
||||
val direction = if (direction == Direction.Ascending) "ASCENDING" else "DESCENDING"
|
||||
return "$type,$direction"
|
||||
|
@ -2,6 +2,7 @@ package tachiyomi.domain.track.interactor
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.domain.track.model.Track
|
||||
import tachiyomi.domain.track.repository.TrackRepository
|
||||
|
||||
class GetTracksPerManga(
|
||||
@ -9,17 +10,14 @@ class GetTracksPerManga(
|
||||
private val isTrackUnfollowed: IsTrackUnfollowed,
|
||||
) {
|
||||
|
||||
fun subscribe(): Flow<Map<Long, List<Long>>> {
|
||||
fun subscribe(): Flow<Map<Long, List<Track>>> {
|
||||
return trackRepository.getTracksAsFlow().map { tracks ->
|
||||
tracks
|
||||
.groupBy { it.mangaId }
|
||||
tracks.groupBy { it.mangaId }
|
||||
// SY -->
|
||||
.mapValues { entry ->
|
||||
entry.value
|
||||
// SY -->
|
||||
.filterNot { isTrackUnfollowed.await(it) }
|
||||
// SY <--
|
||||
.map { it.syncId }
|
||||
entry.value.filterNot { isTrackUnfollowed.await(it) }
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class LibraryFlagsTest {
|
||||
@Test
|
||||
fun `Check the amount of flags`() {
|
||||
LibraryDisplayMode.values.size shouldBe 4
|
||||
LibrarySort.types.size shouldBe 8
|
||||
LibrarySort.types.size shouldBe 9
|
||||
LibrarySort.directions.size shouldBe 2
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
<string name="action_sort_latest_chapter">Latest chapter</string>
|
||||
<string name="action_sort_chapter_fetch_date">Chapter fetch date</string>
|
||||
<string name="action_sort_date_added">Date added</string>
|
||||
<string name="action_sort_tracker_score">Tracker score</string>
|
||||
<string name="action_search">Search</string>
|
||||
<string name="action_search_hint">Search…</string>
|
||||
<string name="action_search_settings">Search settings</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user