mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-12 03:58:56 +01:00
Implement scanlator filter (#8803)
* Implement scanlator filter * Visual improvement to scanlator filter dialog * Review changes + Bug fixes Backup not containing filtered chapters and similar issue fix * Review Changes + Fix SQL query * Lint mamma mia
This commit is contained in:
@@ -414,7 +414,7 @@ class LibraryScreenModel(
|
||||
}
|
||||
|
||||
suspend fun getNextUnreadChapter(manga: Manga): Chapter? {
|
||||
return getChaptersByMangaId.await(manga.id).getNextUnread(manga, downloadManager)
|
||||
return getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true).getNextUnread(manga, downloadManager)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,8 +9,10 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -30,6 +32,7 @@ import eu.kanade.presentation.manga.EditCoverAction
|
||||
import eu.kanade.presentation.manga.MangaScreen
|
||||
import eu.kanade.presentation.manga.components.DeleteChaptersDialog
|
||||
import eu.kanade.presentation.manga.components.MangaCoverDialog
|
||||
import eu.kanade.presentation.manga.components.ScanlatorFilterDialog
|
||||
import eu.kanade.presentation.manga.components.SetIntervalDialog
|
||||
import eu.kanade.presentation.util.AssistContentScreen
|
||||
import eu.kanade.presentation.util.Screen
|
||||
@@ -152,6 +155,8 @@ class MangaScreen(
|
||||
onInvertSelection = screenModel::invertSelection,
|
||||
)
|
||||
|
||||
var showScanlatorsDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val onDismissRequest = { screenModel.dismissDialog() }
|
||||
when (val dialog = successState.dialog) {
|
||||
null -> {}
|
||||
@@ -189,6 +194,8 @@ class MangaScreen(
|
||||
onDisplayModeChanged = screenModel::setDisplayMode,
|
||||
onSetAsDefault = screenModel::setCurrentSettingsAsDefault,
|
||||
onResetToDefault = screenModel::resetToDefaultSettings,
|
||||
scanlatorFilterActive = successState.scanlatorFilterActive,
|
||||
onScanlatorFilterClicked = { showScanlatorsDialog = true },
|
||||
)
|
||||
MangaScreenModel.Dialog.TrackSheet -> {
|
||||
NavigatorAdaptiveSheet(
|
||||
@@ -235,6 +242,15 @@ class MangaScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showScanlatorsDialog) {
|
||||
ScanlatorFilterDialog(
|
||||
availableScanlators = successState.availableScanlators,
|
||||
excludedScanlators = successState.excludedScanlators,
|
||||
onDismissRequest = { showScanlatorsDialog = false },
|
||||
onConfirm = screenModel::setExcludedScanlators,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun continueReading(context: Context, unreadChapter: Chapter?) {
|
||||
|
||||
@@ -11,9 +11,13 @@ import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import eu.kanade.core.preference.asState
|
||||
import eu.kanade.core.util.addOrRemove
|
||||
import eu.kanade.core.util.insertSeparators
|
||||
import eu.kanade.domain.chapter.interactor.GetAvailableScanlators
|
||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||
import eu.kanade.domain.manga.interactor.GetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.SetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.manga.model.chaptersFiltered
|
||||
import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.domain.manga.model.toSManga
|
||||
import eu.kanade.domain.track.interactor.AddTracks
|
||||
@@ -92,6 +96,9 @@ class MangaScreenModel(
|
||||
private val downloadCache: DownloadCache = Injekt.get(),
|
||||
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
||||
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
|
||||
private val getAvailableScanlators: GetAvailableScanlators = Injekt.get(),
|
||||
private val getExcludedScanlators: GetExcludedScanlators = Injekt.get(),
|
||||
private val setExcludedScanlators: SetExcludedScanlators = Injekt.get(),
|
||||
private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(),
|
||||
private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(),
|
||||
private val setReadStatus: SetReadStatus = Injekt.get(),
|
||||
@@ -154,7 +161,7 @@ class MangaScreenModel(
|
||||
init {
|
||||
screenModelScope.launchIO {
|
||||
combine(
|
||||
getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(),
|
||||
getMangaAndChapters.subscribe(mangaId, applyScanlatorFilter = true).distinctUntilChanged(),
|
||||
downloadCache.changes,
|
||||
downloadManager.queueState,
|
||||
) { mangaAndChapters, _, _ -> mangaAndChapters }
|
||||
@@ -168,11 +175,31 @@ class MangaScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
screenModelScope.launchIO {
|
||||
getExcludedScanlators.subscribe(mangaId)
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { excludedScanlators ->
|
||||
updateSuccessState {
|
||||
it.copy(excludedScanlators = excludedScanlators)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
screenModelScope.launchIO {
|
||||
getAvailableScanlators.subscribe(mangaId)
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { availableScanlators ->
|
||||
updateSuccessState {
|
||||
it.copy(availableScanlators = availableScanlators)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
observeDownloads()
|
||||
|
||||
screenModelScope.launchIO {
|
||||
val manga = getMangaAndChapters.awaitManga(mangaId)
|
||||
val chapters = getMangaAndChapters.awaitChapters(mangaId)
|
||||
val chapters = getMangaAndChapters.awaitChapters(mangaId, applyScanlatorFilter = true)
|
||||
.toChapterListItems(manga)
|
||||
|
||||
if (!manga.favorite) {
|
||||
@@ -189,6 +216,8 @@ class MangaScreenModel(
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source),
|
||||
isFromSource = isFromSource,
|
||||
chapters = chapters,
|
||||
availableScanlators = getAvailableScanlators.await(mangaId),
|
||||
excludedScanlators = getExcludedScanlators.await(mangaId),
|
||||
isRefreshingData = needRefreshInfo || needRefreshChapter,
|
||||
dialog = null,
|
||||
)
|
||||
@@ -995,6 +1024,12 @@ class MangaScreenModel(
|
||||
updateSuccessState { it.copy(dialog = Dialog.FullCover) }
|
||||
}
|
||||
|
||||
fun setExcludedScanlators(excludedScanlators: Set<String>) {
|
||||
screenModelScope.launchIO {
|
||||
setExcludedScanlators.await(mangaId, excludedScanlators)
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface State {
|
||||
@Immutable
|
||||
data object Loading : State
|
||||
@@ -1005,12 +1040,13 @@ class MangaScreenModel(
|
||||
val source: Source,
|
||||
val isFromSource: Boolean,
|
||||
val chapters: List<ChapterList.Item>,
|
||||
val availableScanlators: Set<String>,
|
||||
val excludedScanlators: Set<String>,
|
||||
val trackItems: List<TrackItem> = emptyList(),
|
||||
val isRefreshingData: Boolean = false,
|
||||
val dialog: Dialog? = null,
|
||||
val hasPromptedToAddBefore: Boolean = false,
|
||||
) : State {
|
||||
|
||||
val processedChapters by lazy {
|
||||
chapters.applyFilters(manga).toList()
|
||||
}
|
||||
@@ -1042,6 +1078,12 @@ class MangaScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
val scanlatorFilterActive: Boolean
|
||||
get() = excludedScanlators.intersect(availableScanlators).isNotEmpty()
|
||||
|
||||
val filterActive: Boolean
|
||||
get() = scanlatorFilterActive || manga.chaptersFiltered()
|
||||
|
||||
val trackingAvailable: Boolean
|
||||
get() = trackItems.isNotEmpty()
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
*/
|
||||
private val chapterList by lazy {
|
||||
val manga = manga!!
|
||||
val chapters = runBlocking { getChaptersByMangaId.await(manga.id) }
|
||||
val chapters = runBlocking { getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) }
|
||||
|
||||
val selectedChapter = chapters.find { it.id == chapterId }
|
||||
?: error("Requested chapter of id $chapterId not found in chapter list")
|
||||
|
||||
Reference in New Issue
Block a user