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 (cherry picked from commit b97aa235480e35b5514b7b1489b9d4413cea66d9) # Conflicts: # app/build.gradle.kts # app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt # data/src/main/java/tachiyomi/data/chapter/ChapterRepositoryImpl.kt # data/src/main/sqldelight/tachiyomi/migrations/23.sqm # data/src/main/sqldelight/tachiyomi/migrations/26.sqm # domain/src/main/java/tachiyomi/domain/history/interactor/GetNextChapters.kt
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package eu.kanade.domain
|
||||
|
||||
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.download.interactor.DeleteDownload
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
||||
import eu.kanade.domain.extension.interactor.GetExtensionsByType
|
||||
import eu.kanade.domain.manga.interactor.GetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.SetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.source.interactor.GetEnabledSources
|
||||
@@ -112,6 +115,8 @@ class DomainModule : InjektModule {
|
||||
addFactory { NetworkToLocalManga(get()) }
|
||||
addFactory { UpdateManga(get(), get()) }
|
||||
addFactory { SetMangaCategories(get()) }
|
||||
addFactory { GetExcludedScanlators(get()) }
|
||||
addFactory { SetExcludedScanlators(get()) }
|
||||
|
||||
addSingletonFactory<ReleaseService> { ReleaseServiceImpl(get(), get()) }
|
||||
addFactory { GetApplicationRelease(get(), get()) }
|
||||
@@ -133,7 +138,8 @@ class DomainModule : InjektModule {
|
||||
addFactory { UpdateChapter(get()) }
|
||||
addFactory { SetReadStatus(get(), get(), get(), get(), get()) }
|
||||
addFactory { ShouldUpdateDbChapter() }
|
||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get()) }
|
||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) }
|
||||
addFactory { GetAvailableScanlators(get()) }
|
||||
|
||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||
addFactory { GetHistory(get()) }
|
||||
|
||||
@@ -52,7 +52,6 @@ import tachiyomi.domain.manga.interactor.InsertFavoriteEntryAlternative
|
||||
import tachiyomi.domain.manga.interactor.InsertFlatMetadata
|
||||
import tachiyomi.domain.manga.interactor.InsertMergedReference
|
||||
import tachiyomi.domain.manga.interactor.SetCustomMangaInfo
|
||||
import tachiyomi.domain.manga.interactor.SetMangaFilteredScanlators
|
||||
import tachiyomi.domain.manga.interactor.UpdateMergedSettings
|
||||
import tachiyomi.domain.manga.repository.CustomMangaRepository
|
||||
import tachiyomi.domain.manga.repository.FavoritesEntryRepository
|
||||
@@ -88,7 +87,6 @@ class SYDomainModule : InjektModule {
|
||||
addFactory { GetShowLatest(get()) }
|
||||
addFactory { ToggleExcludeFromDataSaver(get()) }
|
||||
addFactory { SetSourceCategories(get()) }
|
||||
addFactory { SetMangaFilteredScanlators(get()) }
|
||||
addFactory { GetAllManga(get()) }
|
||||
addFactory { GetMangaBySource(get()) }
|
||||
addFactory { DeleteChapters(get()) }
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package eu.kanade.domain.chapter.interactor
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.domain.chapter.repository.ChapterRepository
|
||||
|
||||
class GetAvailableScanlators(
|
||||
private val repository: ChapterRepository,
|
||||
) {
|
||||
|
||||
private fun List<String>.cleanupAvailableScanlators(): Set<String> {
|
||||
return mapNotNull { it.ifBlank { null } }.toSet()
|
||||
}
|
||||
|
||||
suspend fun await(mangaId: Long): Set<String> {
|
||||
return repository.getScanlatorsByMangaId(mangaId)
|
||||
.cleanupAvailableScanlators()
|
||||
}
|
||||
|
||||
fun subscribe(mangaId: Long): Flow<Set<String>> {
|
||||
return repository.getScanlatorsByMangaIdAsFlow(mangaId)
|
||||
.map { it.cleanupAvailableScanlators() }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package eu.kanade.domain.chapter.interactor
|
||||
|
||||
import eu.kanade.domain.chapter.model.copyFromSChapter
|
||||
import eu.kanade.domain.chapter.model.toSChapter
|
||||
import eu.kanade.domain.manga.interactor.GetExcludedScanlators
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.manga.model.toSManga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
@@ -34,6 +35,7 @@ class SyncChaptersWithSource(
|
||||
private val updateManga: UpdateManga,
|
||||
private val updateChapter: UpdateChapter,
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId,
|
||||
private val getExcludedScanlators: GetExcludedScanlators,
|
||||
) {
|
||||
|
||||
/**
|
||||
@@ -234,6 +236,10 @@ class SyncChaptersWithSource(
|
||||
|
||||
val reAddedUrls = reAdded.map { it.url }.toHashSet()
|
||||
|
||||
return updatedToAdd.filterNot { it.url in reAddedUrls }
|
||||
val excludedScanlators = getExcludedScanlators.await(manga.id).toHashSet()
|
||||
|
||||
return updatedToAdd.filterNot {
|
||||
it.url in reAddedUrls || it.scanlator in excludedScanlators
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package eu.kanade.domain.chapter.model
|
||||
import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.ui.manga.ChapterList
|
||||
import exh.md.utils.MdUtil
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.chapter.service.getChapterSort
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -16,7 +15,7 @@ import tachiyomi.source.local.isLocal
|
||||
*/
|
||||
fun List<Chapter>.applyFilters(
|
||||
manga: Manga,
|
||||
downloadManager: DownloadManager/* SY --> */,
|
||||
downloadManager: DownloadManager,/* SY --> */
|
||||
mergedManga: Map<Long, Manga>, /* SY <-- */
|
||||
): List<Chapter> {
|
||||
val isLocalManga = manga.isLocal()
|
||||
@@ -41,14 +40,6 @@ fun List<Chapter>.applyFilters(
|
||||
downloaded || isLocalManga
|
||||
}
|
||||
}
|
||||
// SY -->
|
||||
.filter { chapter ->
|
||||
manga.filteredScanlators.isNullOrEmpty() ||
|
||||
MdUtil.getScanlators(chapter.scanlator).any { group ->
|
||||
manga.filteredScanlators!!.contains(group)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
.sortedWith(getChapterSort(manga))
|
||||
}
|
||||
|
||||
@@ -65,13 +56,5 @@ fun List<ChapterList.Item>.applyFilters(manga: Manga): Sequence<ChapterList.Item
|
||||
.filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } }
|
||||
.filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
|
||||
.filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } }
|
||||
// SY -->
|
||||
.filter { chapter ->
|
||||
manga.filteredScanlators.isNullOrEmpty() ||
|
||||
MdUtil.getScanlators(chapter.chapter.scanlator).any { group ->
|
||||
manga.filteredScanlators!!.contains(group)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class GetExcludedScanlators(
|
||||
private val handler: DatabaseHandler,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long): Set<String> {
|
||||
return handler.awaitList {
|
||||
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(mangaId)
|
||||
}
|
||||
.toSet()
|
||||
}
|
||||
|
||||
fun subscribe(mangaId: Long): Flow<Set<String>> {
|
||||
return handler.subscribeToList {
|
||||
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(mangaId)
|
||||
}
|
||||
.map { it.toSet() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class SetExcludedScanlators(
|
||||
private val handler: DatabaseHandler,
|
||||
) {
|
||||
|
||||
suspend fun await(mangaId: Long, excludedScanlators: Set<String>) {
|
||||
handler.await(inTransaction = true) {
|
||||
val currentExcluded = handler.awaitList {
|
||||
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(mangaId)
|
||||
}.toSet()
|
||||
val toAdd = excludedScanlators.minus(currentExcluded)
|
||||
for (scanlator in toAdd) {
|
||||
excluded_scanlatorsQueries.insert(mangaId, scanlator)
|
||||
}
|
||||
val toRemove = currentExcluded.minus(excludedScanlators)
|
||||
excluded_scanlatorsQueries.remove(mangaId, toRemove)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,7 @@ val Manga.downloadedFilter: TriState
|
||||
fun Manga.chaptersFiltered(): Boolean {
|
||||
return unreadFilter != TriState.DISABLED ||
|
||||
downloadedFilter != TriState.DISABLED ||
|
||||
bookmarkedFilter != TriState.DISABLED ||
|
||||
// SY -->
|
||||
!filteredScanlators.isNullOrEmpty()
|
||||
// SY <--
|
||||
bookmarkedFilter != TriState.DISABLED
|
||||
}
|
||||
fun Manga.forceDownloaded(): Boolean {
|
||||
return favorite && Injekt.get<BasePreferences>().downloadedOnly().get()
|
||||
|
||||
@@ -14,6 +14,7 @@ import androidx.compose.material.icons.outlined.PeopleAlt
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
@@ -37,6 +38,7 @@ import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.RadioItem
|
||||
import tachiyomi.presentation.core.components.SortItem
|
||||
import tachiyomi.presentation.core.components.TriStateItem
|
||||
import tachiyomi.presentation.core.theme.active
|
||||
|
||||
@Composable
|
||||
fun ChapterSettingsDialog(
|
||||
@@ -45,13 +47,12 @@ fun ChapterSettingsDialog(
|
||||
onDownloadFilterChanged: (TriState) -> Unit,
|
||||
onUnreadFilterChanged: (TriState) -> Unit,
|
||||
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||
scanlatorFilterActive: Boolean,
|
||||
onScanlatorFilterClicked: (() -> Unit),
|
||||
onSortModeChanged: (Long) -> Unit,
|
||||
onDisplayModeChanged: (Long) -> Unit,
|
||||
onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
|
||||
onResetToDefault: () -> Unit,
|
||||
// SY -->
|
||||
onClickShowScanlatorSelection: (() -> Unit)?,
|
||||
// SY <--
|
||||
) {
|
||||
var showSetAsDefaultDialog by rememberSaveable { mutableStateOf(false) }
|
||||
if (showSetAsDefaultDialog) {
|
||||
@@ -94,14 +95,14 @@ fun ChapterSettingsDialog(
|
||||
0 -> {
|
||||
FilterPage(
|
||||
downloadFilter = manga?.downloadedFilter ?: TriState.DISABLED,
|
||||
onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { manga?.forceDownloaded() == true },
|
||||
onDownloadFilterChanged = onDownloadFilterChanged
|
||||
.takeUnless { manga?.forceDownloaded() == true },
|
||||
unreadFilter = manga?.unreadFilter ?: TriState.DISABLED,
|
||||
onUnreadFilterChanged = onUnreadFilterChanged,
|
||||
bookmarkedFilter = manga?.bookmarkedFilter ?: TriState.DISABLED,
|
||||
onBookmarkedFilterChanged = onBookmarkedFilterChanged,
|
||||
// SY -->
|
||||
onClickShowScanlatorSelection = onClickShowScanlatorSelection,
|
||||
// SY <--
|
||||
scanlatorFilterActive = scanlatorFilterActive,
|
||||
onScanlatorFilterClicked = onScanlatorFilterClicked,
|
||||
)
|
||||
}
|
||||
1 -> {
|
||||
@@ -130,9 +131,8 @@ private fun ColumnScope.FilterPage(
|
||||
onUnreadFilterChanged: (TriState) -> Unit,
|
||||
bookmarkedFilter: TriState,
|
||||
onBookmarkedFilterChanged: (TriState) -> Unit,
|
||||
// SY -->
|
||||
onClickShowScanlatorSelection: (() -> Unit)?,
|
||||
// SY <--
|
||||
scanlatorFilterActive: Boolean,
|
||||
onScanlatorFilterClicked: (() -> Unit),
|
||||
) {
|
||||
TriStateItem(
|
||||
label = stringResource(R.string.label_downloaded),
|
||||
@@ -149,23 +149,20 @@ private fun ColumnScope.FilterPage(
|
||||
state = bookmarkedFilter,
|
||||
onClick = onBookmarkedFilterChanged,
|
||||
)
|
||||
// SY -->
|
||||
if (onClickShowScanlatorSelection != null) {
|
||||
SetScanlatorsItem(onClickShowScanlatorSelection)
|
||||
}
|
||||
// SY <--
|
||||
ScanlatorFilterItem(
|
||||
active = scanlatorFilterActive,
|
||||
onClick = onScanlatorFilterClicked,
|
||||
)
|
||||
}
|
||||
|
||||
// SY -->
|
||||
@Composable
|
||||
private fun SetScanlatorsItem(
|
||||
onClickShowScanlatorSelection: () -> Unit,
|
||||
fun ScanlatorFilterItem(
|
||||
active: Boolean,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
onClick = onClickShowScanlatorSelection,
|
||||
)
|
||||
.clickable(onClick = onClick)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TabbedDialogPaddings.Horizontal, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@@ -174,6 +171,11 @@ private fun SetScanlatorsItem(
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.PeopleAlt,
|
||||
contentDescription = null,
|
||||
tint = if (active) {
|
||||
MaterialTheme.colorScheme.active
|
||||
} else {
|
||||
LocalContentColor.current
|
||||
},
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.scanlator),
|
||||
@@ -181,7 +183,6 @@ private fun SetScanlatorsItem(
|
||||
)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.SortPage(
|
||||
|
||||
@@ -48,7 +48,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.util.fastAll
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import eu.kanade.domain.manga.model.chaptersFiltered
|
||||
import eu.kanade.presentation.manga.components.ChapterDownloadAction
|
||||
import eu.kanade.presentation.manga.components.ChapterHeader
|
||||
import eu.kanade.presentation.manga.components.ExpandableMangaDescription
|
||||
@@ -375,7 +374,7 @@ private fun MangaScreenSmallImpl(
|
||||
title = state.manga.title,
|
||||
titleAlphaProvider = { animatedTitleAlpha },
|
||||
backgroundAlphaProvider = { animatedBgAlpha },
|
||||
hasFilters = state.manga.chaptersFiltered(),
|
||||
hasFilters = state.filterActive,
|
||||
onBackClicked = internalOnBackPressed,
|
||||
onClickFilter = onFilterClicked,
|
||||
onClickShare = onShareClicked,
|
||||
@@ -705,7 +704,7 @@ fun MangaScreenLargeImpl(
|
||||
title = state.manga.title,
|
||||
titleAlphaProvider = { if (isAnySelected) 1f else 0f },
|
||||
backgroundAlphaProvider = { 1f },
|
||||
hasFilters = state.manga.chaptersFiltered(),
|
||||
hasFilters = state.filterActive,
|
||||
onBackClicked = internalOnBackPressed,
|
||||
onClickFilter = onFilterButtonClicked,
|
||||
onClickShare = onShareClicked,
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package eu.kanade.presentation.manga.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
|
||||
import androidx.compose.material.icons.rounded.DisabledByDefault
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.minimumInteractiveComponentSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.presentation.core.components.material.TextButton
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
|
||||
@Composable
|
||||
fun ScanlatorFilterDialog(
|
||||
availableScanlators: Set<String>,
|
||||
excludedScanlators: Set<String>,
|
||||
onDismissRequest: () -> Unit,
|
||||
onConfirm: (Set<String>) -> Unit,
|
||||
) {
|
||||
val sortedAvailableScanlators = remember(availableScanlators) {
|
||||
availableScanlators.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it })
|
||||
}
|
||||
val mutableExcludedScanlators = remember(excludedScanlators) { excludedScanlators.toMutableStateList() }
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.exclude_scanlators)) },
|
||||
text = textFunc@{
|
||||
if (sortedAvailableScanlators.isEmpty()) {
|
||||
Text(text = stringResource(R.string.no_scanlators_found))
|
||||
return@textFunc
|
||||
}
|
||||
Box {
|
||||
val state = rememberLazyListState()
|
||||
LazyColumn(state = state) {
|
||||
sortedAvailableScanlators.forEach { scanlator ->
|
||||
item {
|
||||
val isExcluded = mutableExcludedScanlators.contains(scanlator)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
if (isExcluded) {
|
||||
mutableExcludedScanlators.remove(scanlator)
|
||||
} else {
|
||||
mutableExcludedScanlators.add(scanlator)
|
||||
}
|
||||
}
|
||||
.minimumInteractiveComponentSize()
|
||||
.clip(MaterialTheme.shapes.small)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = MaterialTheme.padding.small),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isExcluded) {
|
||||
Icons.Rounded.DisabledByDefault
|
||||
} else {
|
||||
Icons.Rounded.CheckBoxOutlineBlank
|
||||
},
|
||||
tint = if (isExcluded) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
LocalContentColor.current
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = scanlator,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(start = 24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!state.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
|
||||
if (!state.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
|
||||
}
|
||||
},
|
||||
properties = DialogProperties(
|
||||
usePlatformDefaultWidth = true,
|
||||
),
|
||||
confirmButton = {
|
||||
FlowRow {
|
||||
if (sortedAvailableScanlators.isEmpty()) {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
}
|
||||
return@FlowRow
|
||||
}
|
||||
TextButton(onClick = mutableExcludedScanlators::clear) {
|
||||
Text(text = stringResource(R.string.action_reset))
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
}
|
||||
TextButton(
|
||||
onClick = {
|
||||
onConfirm(mutableExcludedScanlators.toSet())
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -47,7 +47,6 @@ import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.DateColumnAdapter
|
||||
import tachiyomi.data.History
|
||||
import tachiyomi.data.Mangas
|
||||
import tachiyomi.data.StringListAndColumnAdapter
|
||||
import tachiyomi.data.StringListColumnAdapter
|
||||
import tachiyomi.data.UpdateStrategyColumnAdapter
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
@@ -126,9 +125,6 @@ class AppModule(val app: Application) : InjektModule {
|
||||
mangasAdapter = Mangas.Adapter(
|
||||
genreAdapter = StringListColumnAdapter,
|
||||
update_strategyAdapter = UpdateStrategyColumnAdapter,
|
||||
// SY -->
|
||||
filtered_scanlatorsAdapter = StringListAndColumnAdapter,
|
||||
// SY <--
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK
|
||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
|
||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||
@@ -252,10 +253,15 @@ class BackupCreator(
|
||||
// Check if user wants chapter information in backup
|
||||
if (options and BACKUP_CHAPTER_MASK == BACKUP_CHAPTER) {
|
||||
// Backup all the chapters
|
||||
val chapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(manga.id, backupChapterMapper) }
|
||||
if (chapters.isNotEmpty()) {
|
||||
mangaObject.chapters = chapters
|
||||
handler.awaitList {
|
||||
chaptersQueries.getChaptersByMangaId(
|
||||
mangaId = manga.id,
|
||||
applyScanlatorFilter = 0, // false
|
||||
mapper = backupChapterMapper,
|
||||
)
|
||||
}
|
||||
.takeUnless(List<BackupChapter>::isEmpty)
|
||||
?.let { mangaObject.chapters = it }
|
||||
}
|
||||
|
||||
// Check if user wants category information in backup
|
||||
|
||||
@@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||
import exh.EXHMigrations
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import exh.util.nullIfBlank
|
||||
import exh.util.nullIfEmpty
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.isActive
|
||||
import tachiyomi.core.preference.AndroidPreferenceStore
|
||||
@@ -35,7 +34,6 @@ import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.Manga_sync
|
||||
import tachiyomi.data.Mangas
|
||||
import tachiyomi.data.StringListAndColumnAdapter
|
||||
import tachiyomi.data.UpdateStrategyColumnAdapter
|
||||
import tachiyomi.data.manga.MangaMapper
|
||||
import tachiyomi.data.manga.MergedMangaMapper
|
||||
@@ -365,9 +363,6 @@ class BackupRestorer(
|
||||
coverLastModified = manga.coverLastModified,
|
||||
dateAdded = manga.dateAdded,
|
||||
mangaId = manga.id,
|
||||
// SY -->
|
||||
filteredScanlators = manga.filteredScanlators?.let(StringListAndColumnAdapter::encode),
|
||||
// SY <--
|
||||
updateStrategy = manga.updateStrategy.let(UpdateStrategyColumnAdapter::encode),
|
||||
)
|
||||
}
|
||||
@@ -530,9 +525,6 @@ class BackupRestorer(
|
||||
chapterFlags = manga.chapterFlags,
|
||||
coverLastModified = manga.coverLastModified,
|
||||
dateAdded = manga.dateAdded,
|
||||
// SY -->
|
||||
filteredScanlators = manga.filteredScanlators?.nullIfEmpty(),
|
||||
// SY <--
|
||||
updateStrategy = manga.updateStrategy,
|
||||
)
|
||||
mangasQueries.selectLastInsertedRowId()
|
||||
|
||||
@@ -4,7 +4,6 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import tachiyomi.data.StringListAndColumnAdapter
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.CustomMangaInfo
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -79,7 +78,6 @@ data class BackupManga(
|
||||
chapterFlags = this@BackupManga.chapterFlags.toLong(),
|
||||
updateStrategy = this@BackupManga.updateStrategy,
|
||||
lastModifiedAt = this@BackupManga.lastModifiedAt,
|
||||
filteredScanlators = this@BackupManga.filtered_scanlators?.let(StringListAndColumnAdapter::decode),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -141,7 +139,6 @@ data class BackupManga(
|
||||
lastModifiedAt = manga.lastModifiedAt,
|
||||
favoriteModifiedAt = manga.favoriteModifiedAt,
|
||||
// SY -->
|
||||
filtered_scanlators = manga.filteredScanlators?.let(StringListAndColumnAdapter::encode),
|
||||
).also { backupManga ->
|
||||
customMangaInfo?.let {
|
||||
backupManga.customTitle = it.title
|
||||
|
||||
@@ -602,9 +602,9 @@ class LibraryScreenModel(
|
||||
// SY -->
|
||||
val mergedManga = getMergedMangaById.await(manga.id).associateBy { it.id }
|
||||
return if (manga.id == MERGED_SOURCE_ID) {
|
||||
getMergedChaptersByMangaId.await(manga.id)
|
||||
getMergedChaptersByMangaId.await(manga.id, applyScanlatorFilter = true)
|
||||
} else {
|
||||
getChaptersByMangaId.await(manga.id)
|
||||
getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true)
|
||||
}.getNextUnread(manga, downloadManager, mergedManga)
|
||||
// SY <--
|
||||
}
|
||||
|
||||
@@ -33,7 +33,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.SelectScanlatorsDialog
|
||||
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
|
||||
@@ -156,9 +156,17 @@ class MangaScreen(
|
||||
// SY -->
|
||||
onWebViewClicked = {
|
||||
if (successState.mergedData == null) {
|
||||
openMangaInWebView(navigator, screenModel.manga, screenModel.source)
|
||||
openMangaInWebView(
|
||||
navigator,
|
||||
screenModel.manga,
|
||||
screenModel.source
|
||||
)
|
||||
} else {
|
||||
openMergedMangaWebview(context, navigator, successState.mergedData)
|
||||
openMergedMangaWebview(
|
||||
context,
|
||||
navigator,
|
||||
successState.mergedData
|
||||
)
|
||||
}
|
||||
}.takeIf { isHttpSource },
|
||||
// SY <--
|
||||
@@ -199,9 +207,7 @@ class MangaScreen(
|
||||
onInvertSelection = screenModel::invertSelection,
|
||||
)
|
||||
|
||||
// SY -->
|
||||
var showScanlatorsDialog by remember { mutableStateOf(false) }
|
||||
// SY <--
|
||||
|
||||
val onDismissRequest = { screenModel.dismissDialog() }
|
||||
when (val dialog = successState.dialog) {
|
||||
@@ -240,9 +246,8 @@ class MangaScreen(
|
||||
onDisplayModeChanged = screenModel::setDisplayMode,
|
||||
onSetAsDefault = screenModel::setCurrentSettingsAsDefault,
|
||||
onResetToDefault = screenModel::resetToDefaultSettings,
|
||||
// SY -->
|
||||
onClickShowScanlatorSelection = { showScanlatorsDialog = true }.takeIf { successState.scanlators.size > 1 },
|
||||
// SY <--
|
||||
scanlatorFilterActive = successState.scanlatorFilterActive,
|
||||
onScanlatorFilterClicked = { showScanlatorsDialog = true },
|
||||
)
|
||||
MangaScreenModel.Dialog.TrackSheet -> {
|
||||
NavigatorAdaptiveSheet(
|
||||
@@ -306,16 +311,15 @@ class MangaScreen(
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
// SY -->
|
||||
|
||||
if (showScanlatorsDialog) {
|
||||
SelectScanlatorsDialog(
|
||||
ScanlatorFilterDialog(
|
||||
availableScanlators = successState.availableScanlators,
|
||||
excludedScanlators = successState.excludedScanlators,
|
||||
onDismissRequest = { showScanlatorsDialog = false },
|
||||
availableScanlators = successState.scanlators,
|
||||
initialSelectedScanlators = successState.manga.filteredScanlators ?: successState.scanlators,
|
||||
onSelectScanlators = screenModel::setScanlatorFilter,
|
||||
onConfirm = screenModel::setExcludedScanlators,
|
||||
)
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
|
||||
private fun continueReading(context: Context, unreadChapter: Chapter?) {
|
||||
|
||||
@@ -11,11 +11,15 @@ 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.GetPagePreviews
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.manga.model.PagePreview
|
||||
import eu.kanade.domain.manga.model.chaptersFiltered
|
||||
import eu.kanade.domain.manga.model.copyFrom
|
||||
import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.domain.manga.model.toSManga
|
||||
@@ -106,7 +110,6 @@ import tachiyomi.domain.manga.interactor.InsertMergedReference
|
||||
import tachiyomi.domain.manga.interactor.NetworkToLocalManga
|
||||
import tachiyomi.domain.manga.interactor.SetCustomMangaInfo
|
||||
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
|
||||
import tachiyomi.domain.manga.interactor.SetMangaFilteredScanlators
|
||||
import tachiyomi.domain.manga.interactor.UpdateMergedSettings
|
||||
import tachiyomi.domain.manga.model.CustomMangaInfo
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -141,7 +144,6 @@ class MangaScreenModel(
|
||||
// SY -->
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
private val setMangaFilteredScanlators: SetMangaFilteredScanlators = Injekt.get(),
|
||||
private val getMergedChaptersByMangaId: GetMergedChaptersByMangaId = Injekt.get(),
|
||||
private val getMergedMangaById: GetMergedMangaById = Injekt.get(),
|
||||
private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(),
|
||||
@@ -157,6 +159,9 @@ class MangaScreenModel(
|
||||
private val setCustomMangaInfo: SetCustomMangaInfo = Injekt.get(),
|
||||
// SY <--
|
||||
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(),
|
||||
@@ -238,11 +243,11 @@ class MangaScreenModel(
|
||||
|
||||
init {
|
||||
screenModelScope.launchIO {
|
||||
getMangaAndChapters.subscribe(mangaId)
|
||||
getMangaAndChapters.subscribe(mangaId, applyScanlatorFilter = true)
|
||||
.distinctUntilChanged()
|
||||
// SY -->
|
||||
.combine(
|
||||
getMergedChaptersByMangaId.subscribe(mangaId, true)
|
||||
getMergedChaptersByMangaId.subscribe(mangaId, true, applyScanlatorFilter = true)
|
||||
.distinctUntilChanged(),
|
||||
) { (manga, chapters), mergedChapters ->
|
||||
if (manga.source == MERGED_SOURCE_ID) {
|
||||
@@ -311,19 +316,38 @@ class MangaScreenModel(
|
||||
// SY -->
|
||||
meta = raiseMetadata(flatMetadata, it.source),
|
||||
mergedData = mergedData,
|
||||
scanlators = getChapterScanlators(manga, chapters),
|
||||
// SY <--
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// SY -->
|
||||
val chapters = (if (manga.source == MERGED_SOURCE_ID) getMergedChaptersByMangaId.await(mangaId) else getMangaAndChapters.awaitChapters(mangaId))
|
||||
val chapters = (if (manga.source == MERGED_SOURCE_ID) getMergedChaptersByMangaId.await(mangaId, applyScanlatorFilter = true) else getMangaAndChapters.awaitChapters(mangaId, applyScanlatorFilter = true))
|
||||
.toChapterListItems(manga, null)
|
||||
val mergedData = getMergedReferencesById.await(mangaId).takeIf { it.isNotEmpty() }?.let { references ->
|
||||
MergedMangaData(
|
||||
@@ -351,6 +375,8 @@ class MangaScreenModel(
|
||||
source = source,
|
||||
isFromSource = isFromSource,
|
||||
chapters = chapters,
|
||||
availableScanlators = getAvailableScanlators.await(mangaId),
|
||||
excludedScanlators = getExcludedScanlators.await(mangaId),
|
||||
isRefreshingData = needRefreshInfo || needRefreshChapter,
|
||||
dialog = null,
|
||||
// SY -->
|
||||
@@ -365,7 +391,6 @@ class MangaScreenModel(
|
||||
} else {
|
||||
PagePreviewState.Unused
|
||||
},
|
||||
scanlators = getChapterScanlators(manga, chapters.map { it.chapter }),
|
||||
alwaysShowReadingProgress = readerPreferences.preserveReadingPosition().get() && manga.isEhBasedManga(),
|
||||
// SY <--
|
||||
)
|
||||
@@ -424,15 +449,6 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
// SY -->
|
||||
private fun getChapterScanlators(manga: Manga, chapters: List<Chapter>): List<String> {
|
||||
return if (manga.isEhBasedManga()) {
|
||||
emptyList()
|
||||
} else {
|
||||
chapters.flatMap { MdUtil.getScanlators(it.scanlator) }
|
||||
.distinct()
|
||||
}
|
||||
}
|
||||
|
||||
private fun raiseMetadata(flatMetadata: FlatMetadata?, source: Source): RaisedSearchMetadata? {
|
||||
return if (flatMetadata != null) {
|
||||
val metaClass = source.getMainSource<MetadataSource<*, *>>()?.metaClass
|
||||
@@ -1299,15 +1315,6 @@ class MangaScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
fun setScanlatorFilter(filteredScanlators: List<String>) {
|
||||
val manga = manga ?: return
|
||||
screenModelScope.launchIO {
|
||||
setMangaFilteredScanlators.awaitSetFilteredScanlators(manga, filteredScanlators)
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
||||
/**
|
||||
* Sets the active display mode.
|
||||
* @param mode the mode to set.
|
||||
@@ -1535,6 +1542,12 @@ class MangaScreenModel(
|
||||
updateSuccessState { it.copy(dialog = Dialog.FullCover) }
|
||||
}
|
||||
|
||||
fun setExcludedScanlators(excludedScanlators: Set<String>) {
|
||||
screenModelScope.launchIO {
|
||||
setExcludedScanlators.await(mangaId, excludedScanlators)
|
||||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
fun showEditMangaInfoDialog() {
|
||||
mutableState.update { state ->
|
||||
@@ -1570,6 +1583,8 @@ 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: MangaScreenModel.Dialog? = null,
|
||||
@@ -1581,11 +1596,9 @@ class MangaScreenModel(
|
||||
val showMergeInOverflow: Boolean,
|
||||
val showMergeWithAnother: Boolean,
|
||||
val pagePreviewsState: PagePreviewState,
|
||||
val scanlators: List<String>,
|
||||
val alwaysShowReadingProgress: Boolean,
|
||||
// SY <--
|
||||
) : State {
|
||||
|
||||
val processedChapters by lazy {
|
||||
chapters.applyFilters(manga).toList()
|
||||
}
|
||||
@@ -1617,6 +1630,12 @@ class MangaScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
val scanlatorFilterActive: Boolean
|
||||
get() = excludedScanlators.intersect(availableScanlators).isNotEmpty()
|
||||
|
||||
val filterActive: Boolean
|
||||
get() = scanlatorFilterActive || manga.chaptersFiltered()
|
||||
|
||||
val trackingAvailable: Boolean
|
||||
get() = trackItems.isNotEmpty()
|
||||
|
||||
@@ -1638,11 +1657,6 @@ class MangaScreenModel(
|
||||
.filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } }
|
||||
.filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } }
|
||||
.filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } }
|
||||
// SY -->
|
||||
.filter { chapter ->
|
||||
manga.filteredScanlators.isNullOrEmpty() || MdUtil.getScanlators(chapter.chapter.scanlator).any { group -> manga.filteredScanlators!!.contains(group) }
|
||||
}
|
||||
// SY <--
|
||||
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,10 +181,10 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
// SY -->
|
||||
val (chapters, mangaMap) = runBlocking {
|
||||
if (manga.source == MERGED_SOURCE_ID) {
|
||||
getMergedChaptersByMangaId.await(manga.id) to getMergedMangaById.await(manga.id)
|
||||
getMergedChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to getMergedMangaById.await(manga.id)
|
||||
.associateBy { it.id }
|
||||
} else {
|
||||
getChaptersByMangaId.await(manga.id) to null
|
||||
getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true) to null
|
||||
}
|
||||
}
|
||||
fun isChapterDownloaded(chapter: Chapter): Boolean {
|
||||
@@ -220,13 +220,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
) ||
|
||||
// SY <--
|
||||
(manga.bookmarkedFilterRaw == Manga.CHAPTER_SHOW_BOOKMARKED && !it.bookmark) ||
|
||||
(manga.bookmarkedFilterRaw == Manga.CHAPTER_SHOW_NOT_BOOKMARKED && it.bookmark) ||
|
||||
// SY -->
|
||||
(
|
||||
manga.filteredScanlators != null && MdUtil.getScanlators(it.scanlator)
|
||||
.none { group -> manga.filteredScanlators!!.contains(group) }
|
||||
)
|
||||
// SY <--
|
||||
(manga.bookmarkedFilterRaw == Manga.CHAPTER_SHOW_NOT_BOOKMARKED && it.bookmark)
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user