Adaptive tags suggestion

feature/double_reader
Koitharu 3 years ago
parent 861be7614e
commit ed87292921
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -51,6 +51,28 @@ abstract class TagsDao {
) )
abstract suspend fun findTags(query: String, limit: Int): List<TagEntity> abstract suspend fun findTags(query: String, limit: Int): List<TagEntity>
@Query(
"""
SELECT tags.* FROM manga_tags
LEFT JOIN tags ON tags.tag_id = manga_tags.tag_id
WHERE manga_tags.manga_id IN (SELECT manga_id FROM manga_tags WHERE tag_id = :tagId)
GROUP BY tags.tag_id
ORDER BY COUNT(manga_id) DESC;
""",
)
abstract suspend fun findRelatedTags(tagId: Long): List<TagEntity>
@Query(
"""
SELECT tags.* FROM manga_tags
LEFT JOIN tags ON tags.tag_id = manga_tags.tag_id
WHERE manga_tags.manga_id IN (SELECT manga_id FROM manga_tags WHERE tag_id IN (:ids))
GROUP BY tags.tag_id
ORDER BY COUNT(manga_id) DESC;
""",
)
abstract suspend fun findRelatedTags(ids: Set<Long>): List<TagEntity>
@Upsert @Upsert
abstract suspend fun upsert(tags: Iterable<TagEntity>) abstract suspend fun upsert(tags: Iterable<TagEntity>)
} }

@ -19,6 +19,8 @@ fun TagEntity.toMangaTag() = MangaTag(
fun Collection<TagEntity>.toMangaTags() = mapToSet(TagEntity::toMangaTag) fun Collection<TagEntity>.toMangaTags() = mapToSet(TagEntity::toMangaTag)
fun Collection<TagEntity>.toMangaTagsList() = map(TagEntity::toMangaTag)
fun MangaEntity.toManga(tags: Set<MangaTag>) = Manga( fun MangaEntity.toManga(tags: Set<MangaTag>) = Manga(
id = this.id, id = this.id,
title = this.title, title = this.title,

@ -131,7 +131,7 @@ class FilterCoordinator @Inject constructor(
observeState(), observeState(),
observeAvailableTags(), observeAvailableTags(),
) { state, available -> ) { state, available ->
val chips = createChipsList(state, available.orEmpty()) val chips = createChipsList(state, available.orEmpty(), 8)
FilterHeaderModel(chips, state.sortOrder, state.tags.isNotEmpty()) FilterHeaderModel(chips, state.sortOrder, state.tags.isNotEmpty())
} }
@ -157,11 +157,16 @@ class FilterCoordinator @Inject constructor(
private suspend fun createChipsList( private suspend fun createChipsList(
filterState: FilterState, filterState: FilterState,
availableTags: Set<MangaTag>, availableTags: Set<MangaTag>,
limit: Int,
): List<ChipsView.ChipModel> { ): List<ChipsView.ChipModel> {
val selectedTags = filterState.tags.toMutableSet() val selectedTags = filterState.tags.toMutableSet()
var tags = searchRepository.getTagsSuggestion("", 6, repository.source) var tags = if (selectedTags.isEmpty()) {
if (tags.isEmpty()) { searchRepository.getTagsSuggestion("", limit, repository.source)
tags = availableTags.take(6) } else {
searchRepository.getTagsSuggestion(selectedTags).take(limit)
}
if (tags.size < limit) {
tags = tags + availableTags.take(limit - tags.size)
} }
if (tags.isEmpty() && selectedTags.isEmpty()) { if (tags.isEmpty() && selectedTags.isEmpty()) {
return emptyList() return emptyList()

@ -10,8 +10,10 @@ import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.toEntity
import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toManga
import org.koitharu.kotatsu.core.db.entity.toMangaTag import org.koitharu.kotatsu.core.db.entity.toMangaTag
import org.koitharu.kotatsu.core.db.entity.toMangaTagsList
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
@ -19,6 +21,7 @@ import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.util.levenshteinDistance import org.koitharu.kotatsu.parsers.util.levenshteinDistance
import org.koitharu.kotatsu.parsers.util.mapToSet
import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider
import javax.inject.Inject import javax.inject.Inject
@ -93,8 +96,17 @@ class MangaSearchRepository @Inject constructor(
query.isNotEmpty() -> db.tagsDao.findTags("%$query%", limit) query.isNotEmpty() -> db.tagsDao.findTags("%$query%", limit)
source != null -> db.tagsDao.findPopularTags(source.name, limit) source != null -> db.tagsDao.findPopularTags(source.name, limit)
else -> db.tagsDao.findPopularTags(limit) else -> db.tagsDao.findPopularTags(limit)
}.map { }.toMangaTagsList()
it.toMangaTag() }
suspend fun getTagsSuggestion(tags: Set<MangaTag>): List<MangaTag> {
val ids = tags.mapToSet { it.toEntity().id }
return if (ids.size == 1) {
db.tagsDao.findRelatedTags(ids.first())
} else {
db.tagsDao.findRelatedTags(ids)
}.mapNotNull { x ->
if (x.id in ids) null else x.toMangaTag()
} }
} }

Loading…
Cancel
Save