Observe tracker login state instead of fetching once (mihonapp/mihon#987)
* Observe tracker login state instead of fetching once * Review changes (cherry picked from commit 2092c81bad59fd745a8514af320e534ecf40a5da) # Conflicts: # app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt
This commit is contained in:
parent
274aefb3b3
commit
e5c830d08b
12 changed files with 142 additions and 62 deletions
|
|
@ -92,6 +92,7 @@ fun LibrarySettingsDialog(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedReceiverParameter")
|
||||
@Composable
|
||||
private fun ColumnScope.FilterPage(
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
|
|
@ -155,7 +156,7 @@ private fun ColumnScope.FilterPage(
|
|||
)
|
||||
// SY <--
|
||||
|
||||
val trackers = remember { screenModel.trackers }
|
||||
val trackers by screenModel.trackersFlow.collectAsState()
|
||||
when (trackers.size) {
|
||||
0 -> {
|
||||
// No trackers
|
||||
|
|
@ -183,11 +184,13 @@ private fun ColumnScope.FilterPage(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedReceiverParameter")
|
||||
@Composable
|
||||
private fun ColumnScope.SortPage(
|
||||
category: Category?,
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
) {
|
||||
val trackers by screenModel.trackersFlow.collectAsState()
|
||||
// SY -->
|
||||
val globalSortMode by screenModel.libraryPreferences.sortingMode().collectAsState()
|
||||
val sortingMode = if (screenModel.grouping == LibraryGroup.BY_DEFAULT) {
|
||||
|
|
@ -206,12 +209,11 @@ private fun ColumnScope.SortPage(
|
|||
}.collectAsState(initial = screenModel.libraryPreferences.sortTagsForLibrary().get().isNotEmpty())
|
||||
// SY <--
|
||||
|
||||
val trackerSortOption =
|
||||
if (screenModel.trackers.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
|
||||
}
|
||||
val trackerSortOption = if (trackers.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
|
||||
}
|
||||
|
||||
listOfNotNull(
|
||||
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,
|
||||
|
|
@ -256,6 +258,7 @@ private val displayModes = listOf(
|
|||
MR.strings.action_display_list to LibraryDisplayMode.List,
|
||||
)
|
||||
|
||||
@Suppress("UnusedReceiverParameter")
|
||||
@Composable
|
||||
private fun ColumnScope.DisplayPage(
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
|
|
@ -341,17 +344,19 @@ private fun groupTypeDrawableRes(type: Int): Int {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedReceiverParameter")
|
||||
@Composable
|
||||
private fun ColumnScope.GroupPage(
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
hasCategories: Boolean,
|
||||
) {
|
||||
val groups = remember(hasCategories, screenModel.trackers) {
|
||||
val trackers by screenModel.trackersFlow.collectAsState()
|
||||
val groups = remember(hasCategories, trackers) {
|
||||
buildList {
|
||||
add(LibraryGroup.BY_DEFAULT)
|
||||
add(LibraryGroup.BY_SOURCE)
|
||||
add(LibraryGroup.BY_STATUS)
|
||||
if (screenModel.trackers.isNotEmpty()) {
|
||||
if (trackers.isNotEmpty()) {
|
||||
add(LibraryGroup.BY_TRACK_STATUS)
|
||||
}
|
||||
if (hasCategories) {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ import androidx.compose.animation.fadeOut
|
|||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.structuralEqualityPolicy
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.track.service.TrackPreferences
|
||||
import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget
|
||||
import eu.kanade.presentation.more.settings.widget.InfoWidget
|
||||
import eu.kanade.presentation.more.settings.widget.ListPreferenceWidget
|
||||
|
|
@ -23,8 +23,6 @@ import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget
|
|||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.presentation.core.components.SliderItem
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
val LocalPreferenceHighlighted = compositionLocalOf(structuralEqualityPolicy()) { false }
|
||||
val LocalPreferenceMinHeight = compositionLocalOf(structuralEqualityPolicy()) { 56.dp }
|
||||
|
|
@ -156,16 +154,14 @@ internal fun PreferenceItem(
|
|||
)
|
||||
}
|
||||
is Preference.PreferenceItem.TrackerPreference -> {
|
||||
val uName by Injekt.get<TrackPreferences>()
|
||||
.trackUsername(item.tracker)
|
||||
.collectAsState()
|
||||
item.tracker.run {
|
||||
TrackingPreferenceWidget(
|
||||
tracker = this,
|
||||
checked = uName.isNotEmpty(),
|
||||
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
||||
)
|
||||
val isLoggedIn by item.tracker.let { tracker ->
|
||||
tracker.isLoggedInFlow.collectAsState(tracker.isLoggedIn)
|
||||
}
|
||||
TrackingPreferenceWidget(
|
||||
tracker = item.tracker,
|
||||
checked = isLoggedIn,
|
||||
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
||||
)
|
||||
}
|
||||
is Preference.PreferenceItem.InfoPreference -> {
|
||||
InfoWidget(text = item.title)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import eu.kanade.domain.track.service.TrackPreferences
|
|||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import logcat.LogPriority
|
||||
import okhttp3.OkHttpClient
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
|
|
@ -53,6 +55,15 @@ abstract class BaseTracker(
|
|||
get() = getUsername().isNotEmpty() &&
|
||||
getPassword().isNotEmpty()
|
||||
|
||||
override val isLoggedInFlow: Flow<Boolean> by lazy {
|
||||
combine(
|
||||
trackPreferences.trackUsername(this).changes(),
|
||||
trackPreferences.trackPassword(this).changes(),
|
||||
) { username, password ->
|
||||
username.isNotEmpty() && password.isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUsername() = trackPreferences.trackUsername(this).get()
|
||||
|
||||
override fun getPassword() = trackPreferences.trackPassword(this).get()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import dev.icerock.moko.resources.StringResource
|
|||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import okhttp3.OkHttpClient
|
||||
import tachiyomi.domain.track.model.Track as DomainTrack
|
||||
|
||||
|
|
@ -61,6 +62,8 @@ interface Tracker {
|
|||
|
||||
val isLoggedIn: Boolean
|
||||
|
||||
val isLoggedInFlow: Flow<Boolean>
|
||||
|
||||
fun getUsername(): String
|
||||
|
||||
fun getPassword(): String
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.track.mdlist.MdList
|
|||
import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeList
|
||||
import eu.kanade.tachiyomi.data.track.shikimori.Shikimori
|
||||
import eu.kanade.tachiyomi.data.track.suwayomi.Suwayomi
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class TrackerManager {
|
||||
|
||||
|
|
@ -40,5 +41,13 @@ class TrackerManager {
|
|||
|
||||
fun loggedInTrackers() = trackers.filter { it.isLoggedIn }
|
||||
|
||||
fun loggedInTrackersFlow() = combine(trackers.map { it.isLoggedInFlow }) {
|
||||
it.mapIndexedNotNull { index, isLoggedIn ->
|
||||
if (isLoggedIn) trackers[index] else null
|
||||
}
|
||||
}
|
||||
|
||||
fun get(id: Long) = trackers.find { it.id == id }
|
||||
|
||||
fun getAll(ids: Set<Long>) = trackers.filter { it.id in ids }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import kotlinx.coroutines.flow.debounce
|
|||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -177,18 +178,24 @@ class LibraryScreenModel(
|
|||
::Pair,
|
||||
),
|
||||
// SY <--
|
||||
) { searchQuery, library, tracks, (loggedInTrackers, _), (groupType, sort) ->
|
||||
) { searchQuery, library, tracks, (trackingFiler, _), (groupType, sort) ->
|
||||
library
|
||||
// SY -->
|
||||
.applyGrouping(groupType)
|
||||
// SY <--
|
||||
.applyFilters(tracks, loggedInTrackers)
|
||||
.applySort(tracks, /* SY --> */sort.takeIf { groupType != LibraryGroup.BY_DEFAULT } /* SY <-- */)
|
||||
.applyFilters(tracks, trackingFiler)
|
||||
.applySort(
|
||||
tracks,
|
||||
trackingFiler.keys,
|
||||
// SY -->
|
||||
sort.takeIf { groupType != LibraryGroup.BY_DEFAULT },
|
||||
// SY <--
|
||||
)
|
||||
.mapValues { (_, value) ->
|
||||
if (searchQuery != null) {
|
||||
// Filter query
|
||||
// SY -->
|
||||
filterLibrary(value, searchQuery, loggedInTrackers)
|
||||
filterLibrary(value, searchQuery, trackingFiler)
|
||||
// SY <--
|
||||
} else {
|
||||
// Don't do anything
|
||||
|
|
@ -277,9 +284,10 @@ class LibraryScreenModel(
|
|||
/**
|
||||
* Applies library filters to the given map of manga.
|
||||
*/
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private suspend fun LibraryMap.applyFilters(
|
||||
trackMap: Map<Long, List<Track>>,
|
||||
loggedInTrackers: Map<Long, TriState>,
|
||||
trackingFiler: Map<Long, TriState>,
|
||||
): LibraryMap {
|
||||
val prefs = getLibraryItemPreferencesFlow().first()
|
||||
val downloadedOnly = prefs.globalFilterDownloaded
|
||||
|
|
@ -291,10 +299,10 @@ class LibraryScreenModel(
|
|||
val filterCompleted = prefs.filterCompleted
|
||||
val filterIntervalCustom = prefs.filterIntervalCustom
|
||||
|
||||
val isNotLoggedInAnyTrack = loggedInTrackers.isEmpty()
|
||||
val isNotLoggedInAnyTrack = trackingFiler.isEmpty()
|
||||
|
||||
val excludedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_NOT) it.key else null }
|
||||
val includedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null }
|
||||
val excludedTracks = trackingFiler.mapNotNull { if (it.value == TriState.ENABLED_NOT) it.key else null }
|
||||
val includedTracks = trackingFiler.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null }
|
||||
val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty()
|
||||
|
||||
// SY -->
|
||||
|
|
@ -371,9 +379,11 @@ class LibraryScreenModel(
|
|||
/**
|
||||
* Applies library sorting to the given map of manga.
|
||||
*/
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
private fun LibraryMap.applySort(
|
||||
// Map<MangaId, List<Track>>
|
||||
trackMap: Map<Long, List<Track>>,
|
||||
loggedInTrackerIds: Set<Long>,
|
||||
/* SY --> */
|
||||
groupSort: LibrarySort? = null, /* SY <-- */
|
||||
): LibraryMap {
|
||||
|
|
@ -397,7 +407,7 @@ class LibraryScreenModel(
|
|||
|
||||
val defaultTrackerScoreSortValue = -1.0
|
||||
val trackerScores by lazy {
|
||||
val trackerMap = trackerManager.loggedInTrackers().associateBy { e -> e.id }
|
||||
val trackerMap = trackerManager.getAll(loggedInTrackerIds).associateBy { e -> e.id }
|
||||
trackMap.mapValues { entry ->
|
||||
when {
|
||||
entry.value.isEmpty() -> null
|
||||
|
|
@ -596,18 +606,17 @@ class LibraryScreenModel(
|
|||
* @return map of track id with the filter value
|
||||
*/
|
||||
private fun getTrackingFilterFlow(): Flow<Map<Long, TriState>> {
|
||||
val loggedInTrackers = trackerManager.loggedInTrackers()
|
||||
return if (loggedInTrackers.isNotEmpty()) {
|
||||
val prefFlows = loggedInTrackers
|
||||
.map { libraryPreferences.filterTracking(it.id.toInt()).changes() }
|
||||
.toTypedArray()
|
||||
combine(*prefFlows) {
|
||||
return trackerManager.loggedInTrackersFlow().flatMapLatest { loggedInTrackers ->
|
||||
if (loggedInTrackers.isEmpty()) return@flatMapLatest flowOf(emptyMap())
|
||||
|
||||
val prefFlows = loggedInTrackers.map { tracker ->
|
||||
libraryPreferences.filterTracking(tracker.id.toInt()).changes()
|
||||
}
|
||||
combine(prefFlows) {
|
||||
loggedInTrackers
|
||||
.mapIndexed { index, tracker -> tracker.id to it[index] }
|
||||
.toMap()
|
||||
}
|
||||
} else {
|
||||
flowOf(emptyMap())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -878,7 +887,6 @@ class LibraryScreenModel(
|
|||
}
|
||||
|
||||
// SY -->
|
||||
|
||||
fun getCategoryName(
|
||||
context: Context,
|
||||
category: Category?,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import cafe.adriel.voyager.core.model.screenModelScope
|
|||
import eu.kanade.core.preference.asState
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
|
@ -18,17 +20,22 @@ import tachiyomi.domain.library.model.LibrarySort
|
|||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class LibrarySettingsScreenModel(
|
||||
val preferences: BasePreferences = Injekt.get(),
|
||||
val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
private val setDisplayMode: SetDisplayMode = Injekt.get(),
|
||||
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
trackerManager: TrackerManager = Injekt.get(),
|
||||
) : ScreenModel {
|
||||
|
||||
val trackers
|
||||
get() = trackerManager.trackers.filter { it.isLoggedIn }
|
||||
val trackersFlow = trackerManager.loggedInTrackersFlow()
|
||||
.stateIn(
|
||||
scope = screenModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds),
|
||||
initialValue = trackerManager.loggedInTrackers()
|
||||
)
|
||||
|
||||
// SY -->
|
||||
val grouping by libraryPreferences.groupLibraryBy().asState(screenModelScope)
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ class MangaScreen(
|
|||
)
|
||||
}.takeIf { isHttpSource },
|
||||
onTrackingClicked = {
|
||||
if (screenModel.loggedInTrackers.isEmpty()) {
|
||||
if (successState.loggedInTracker.isEmpty()) {
|
||||
navigator.push(SettingsScreen(SettingsScreen.Destination.Tracking))
|
||||
} else {
|
||||
screenModel.showTrackDialog()
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import eu.kanade.tachiyomi.data.download.DownloadCache
|
|||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.data.track.mdlist.MdList
|
||||
import eu.kanade.tachiyomi.network.HttpException
|
||||
|
|
@ -166,8 +167,10 @@ import androidx.compose.runtime.State as RuntimeState
|
|||
class MangaScreenModel(
|
||||
val context: Context,
|
||||
val mangaId: Long,
|
||||
// SY -->
|
||||
private val isFromSource: Boolean,
|
||||
val smartSearched: Boolean,
|
||||
// SY <--
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||
readerPreferences: ReaderPreferences = Injekt.get(),
|
||||
|
|
@ -219,8 +222,6 @@ class MangaScreenModel(
|
|||
private val successState: State.Success?
|
||||
get() = state.value as? State.Success
|
||||
|
||||
val loggedInTrackers by lazy { trackerManager.trackers.filter { it.isLoggedIn } }
|
||||
|
||||
// KMK -->
|
||||
val useNewSourceNavigation by uiPreferences.useNewSourceNavigation().asState(screenModelScope)
|
||||
val themeCoverBased = uiPreferences.themeCoverBased().get()
|
||||
|
|
@ -246,7 +247,8 @@ class MangaScreenModel(
|
|||
|
||||
private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope)
|
||||
|
||||
val isUpdateIntervalEnabled = LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get()
|
||||
val isUpdateIntervalEnabled =
|
||||
LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get()
|
||||
|
||||
private val selectedPositions: Array<Int> = arrayOf(-1, -1) // first and last selected index in list
|
||||
private val selectedChapterIds: HashSet<Long> = HashSet()
|
||||
|
|
@ -259,6 +261,7 @@ class MangaScreenModel(
|
|||
data class EXHRedirect(val mangaId: Long)
|
||||
// EXH <--
|
||||
|
||||
// SY -->
|
||||
private data class CombineState(
|
||||
val manga: Manga,
|
||||
val chapters: List<Chapter>,
|
||||
|
|
@ -269,6 +272,7 @@ class MangaScreenModel(
|
|||
constructor(pair: Pair<Manga, List<Chapter>>, flatMetadata: FlatMetadata?) :
|
||||
this(pair.first, pair.second, flatMetadata)
|
||||
}
|
||||
// SY <--
|
||||
|
||||
/**
|
||||
* Helper function to update the UI state only if it's currently in success state
|
||||
|
|
@ -284,8 +288,7 @@ class MangaScreenModel(
|
|||
|
||||
init {
|
||||
screenModelScope.launchIO {
|
||||
getMangaAndChapters.subscribe(mangaId, applyScanlatorFilter = true)
|
||||
.distinctUntilChanged()
|
||||
getMangaAndChapters.subscribe(mangaId, applyScanlatorFilter = true).distinctUntilChanged()
|
||||
// SY -->
|
||||
.combine(
|
||||
getMergedChaptersByMangaId.subscribe(mangaId, true, applyScanlatorFilter = true)
|
||||
|
|
@ -397,6 +400,16 @@ class MangaScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
screenModelScope.launchIO {
|
||||
trackerManager.loggedInTrackersFlow()
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { trackers ->
|
||||
updateSuccessState {
|
||||
it.copy(loggedInTracker = trackers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
observeDownloads()
|
||||
|
||||
screenModelScope.launchIO {
|
||||
|
|
@ -425,7 +438,9 @@ class MangaScreenModel(
|
|||
|
||||
// Show what we have earlier
|
||||
mutableState.update {
|
||||
// SY -->
|
||||
val source = sourceManager.getOrStub(manga.source)
|
||||
// SY <--
|
||||
State.Success(
|
||||
manga = manga,
|
||||
source = source,
|
||||
|
|
@ -1099,7 +1114,9 @@ class MangaScreenModel(
|
|||
|
||||
private fun List<Chapter>.toChapterListItems(
|
||||
manga: Manga,
|
||||
// SY -->
|
||||
mergedData: MergedMangaData?,
|
||||
// SY <--
|
||||
): List<ChapterList.Item> {
|
||||
val isLocal = manga.isLocal()
|
||||
// SY -->
|
||||
|
|
@ -1175,7 +1192,9 @@ class MangaScreenModel(
|
|||
val state = successState ?: return
|
||||
try {
|
||||
withIOContext {
|
||||
// SY -->
|
||||
if (state.source !is MergedSource) {
|
||||
// SY <--
|
||||
val chapters = state.source.getChapterList(state.manga.toSManga())
|
||||
|
||||
val newChapters = syncChaptersWithSource.await(
|
||||
|
|
@ -1188,9 +1207,11 @@ class MangaScreenModel(
|
|||
if (manualFetch) {
|
||||
downloadNewChapters(newChapters)
|
||||
}
|
||||
// SY -->
|
||||
} else {
|
||||
state.source.fetchChaptersForMergedManga(state.manga, manualFetch)
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
val message = if (e is NoChaptersException) {
|
||||
|
|
@ -1471,6 +1492,7 @@ class MangaScreenModel(
|
|||
* @param chapters the list of chapters to download.
|
||||
*/
|
||||
private fun downloadChapters(chapters: List<Chapter>) {
|
||||
// SY -->
|
||||
val state = successState ?: return
|
||||
if (state.source is MergedSource) {
|
||||
chapters.groupBy { it.mangaId }.forEach { map ->
|
||||
|
|
@ -1478,7 +1500,7 @@ class MangaScreenModel(
|
|||
downloadManager.downloadChapters(manga, map.value)
|
||||
}
|
||||
} else {
|
||||
/* SY <-- */
|
||||
// SY <--
|
||||
val manga = state.manga
|
||||
downloadManager.downloadChapters(manga, chapters)
|
||||
}
|
||||
|
|
@ -1524,7 +1546,15 @@ class MangaScreenModel(
|
|||
screenModelScope.launchNonCancellable {
|
||||
val manga = successState?.manga ?: return@launchNonCancellable
|
||||
val categories = getCategories.await(manga.id).map { it.id }
|
||||
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences) || manga.isEhBasedManga()) return@launchNonCancellable
|
||||
if (
|
||||
chapters.isEmpty() ||
|
||||
!manga.shouldDownloadNewChapters(categories, downloadPreferences) ||
|
||||
// EXH -->
|
||||
manga.isEhBasedManga()
|
||||
// EXH <--
|
||||
) {
|
||||
return@launchNonCancellable
|
||||
}
|
||||
downloadChapters(chapters)
|
||||
}
|
||||
}
|
||||
|
|
@ -1721,15 +1751,16 @@ class MangaScreenModel(
|
|||
val manga = state?.manga ?: return
|
||||
|
||||
screenModelScope.launchIO {
|
||||
getTracks.subscribe(manga.id)
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.map { tracks ->
|
||||
loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service -> TrackItem(tracks.find { it.trackerId == service.id }, service) }
|
||||
// Show only if the service supports this manga's source
|
||||
.filter { (it.tracker as? EnhancedTracker)?.accept(source!!) ?: true }
|
||||
}
|
||||
combine(
|
||||
getTracks.subscribe(manga.id).catch { logcat(LogPriority.ERROR, it) },
|
||||
trackerManager.loggedInTrackersFlow(),
|
||||
) { mangaTracks, loggedInTrackers ->
|
||||
loggedInTrackers
|
||||
// Map to TrackItem
|
||||
.map { service -> TrackItem(mangaTracks.find { it.trackerId == service.id }, service) }
|
||||
// Show only if the service supports this manga's source
|
||||
.filter { (it.tracker as? EnhancedTracker)?.accept(source!!) ?: true }
|
||||
}
|
||||
// SY -->
|
||||
.map { trackItems ->
|
||||
if (manga.source in mangaDexSourceIds || state.mergedData?.manga?.values.orEmpty().any {
|
||||
|
|
@ -1869,6 +1900,8 @@ class MangaScreenModel(
|
|||
val isRefreshingData: Boolean = false,
|
||||
val dialog: MangaScreenModel.Dialog? = null,
|
||||
val hasPromptedToAddBefore: Boolean = false,
|
||||
val loggedInTracker: List<Tracker> = emptyList(),
|
||||
|
||||
// SY -->
|
||||
val meta: RaisedSearchMetadata?,
|
||||
val mergedData: MergedMangaData?,
|
||||
|
|
@ -1950,7 +1983,10 @@ class MangaScreenModel(
|
|||
|
||||
val trackingCount: Int
|
||||
get() = trackItems.count {
|
||||
it.track != null && ((it.tracker is MdList && it.track.status != FollowStatus.UNFOLLOWED.long) || it.tracker !is MdList)
|
||||
it.track != null && (
|
||||
it.tracker !is MdList ||
|
||||
it.track.status != FollowStatus.UNFOLLOWED.long
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1972,11 +2008,13 @@ class MangaScreenModel(
|
|||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
data class MergedMangaData(
|
||||
val references: List<MergedMangaReference>,
|
||||
val manga: Map<Long, Manga>,
|
||||
val sources: List<Source>,
|
||||
)
|
||||
// SY <--
|
||||
|
||||
@Immutable
|
||||
sealed class ChapterList {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ data class TrackInfoDialogHomeScreen(
|
|||
}
|
||||
|
||||
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
|
||||
val loggedInTrackers = Injekt.get<TrackerManager>().trackers.filter { it.isLoggedIn }
|
||||
val loggedInTrackers = Injekt.get<TrackerManager>().loggedInTrackers()
|
||||
val source = Injekt.get<SourceManager>().getOrStub(sourceId)
|
||||
return loggedInTrackers
|
||||
// Map to TrackItem
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class StatsScreenModel(
|
|||
// SY <--
|
||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||
|
||||
private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn } }
|
||||
private val loggedInTrackers by lazy { trackerManager.loggedInTrackers() }
|
||||
|
||||
// SY -->
|
||||
private val _allRead = MutableStateFlow(false)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.data.track.Tracker
|
|||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import okhttp3.OkHttpClient
|
||||
import tachiyomi.domain.track.model.Track
|
||||
import tachiyomi.i18n.MR
|
||||
|
|
@ -16,6 +18,7 @@ data class DummyTracker(
|
|||
override val name: String,
|
||||
override val supportsReadingDates: Boolean = false,
|
||||
override val isLoggedIn: Boolean = false,
|
||||
override val isLoggedInFlow: Flow<Boolean> = flowOf(false),
|
||||
val valLogoColor: Int = Color.rgb(18, 25, 35),
|
||||
val valLogo: Int = R.drawable.ic_tracker_anilist,
|
||||
val valStatuses: List<Long> = (1L..6L).toList(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue