Option to not show Related titles by default but using a button to open that screen

This commit is contained in:
Cuong M. Tran 2024-06-12 13:11:07 +07:00
parent 9a39a66dbc
commit 95fef0d019
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
11 changed files with 220 additions and 77 deletions

View file

@ -45,6 +45,8 @@ class UiPreferences(
fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false) fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false)
fun expandRelatedTitles() = preferenceStore.getBoolean("expand_related_titles", true)
fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", true) fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", true)
fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", true) fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", true)

View file

@ -17,19 +17,19 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowForward import androidx.compose.material.icons.automirrored.outlined.ArrowForward
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.browse.components.RelatedMangasComfortableGrid import eu.kanade.presentation.browse.components.RelatedMangasComfortableGrid
import eu.kanade.presentation.browse.components.RelatedMangasCompactGrid import eu.kanade.presentation.browse.components.RelatedMangasCompactGrid
import eu.kanade.presentation.browse.components.RelatedMangasList import eu.kanade.presentation.browse.components.RelatedMangasList
import eu.kanade.tachiyomi.ui.manga.RelatedManga import eu.kanade.tachiyomi.ui.manga.RelatedManga
import exh.util.capitalize
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -115,12 +115,14 @@ fun RelatedMangaTitle(
onClick: () -> Unit, onClick: () -> Unit,
onLongClick: (() -> Unit)?, onLongClick: (() -> Unit)?,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
showArrow: Boolean = true,
) { ) {
Row( Row(
modifier = modifier modifier = modifier
.padding( .padding(
start = MaterialTheme.padding.medium, start = MaterialTheme.padding.medium,
end = MaterialTheme.padding.extraSmall, end = MaterialTheme.padding.small,
top = MaterialTheme.padding.small,
) )
.fillMaxWidth() .fillMaxWidth()
.let { .let {
@ -130,7 +132,7 @@ fun RelatedMangaTitle(
it.combinedClickable(onClick = onClick, onLongClick = onLongClick) it.combinedClickable(onClick = onClick, onLongClick = onLongClick)
} }
}, },
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = if (showArrow) Arrangement.SpaceBetween else Arrangement.Center,
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Column( Column(
@ -140,14 +142,14 @@ fun RelatedMangaTitle(
), ),
) { ) {
Text( Text(
text = title.capitalize(), text = title.capitalize(Locale.current),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
) )
if (subtitle != null) { if (subtitle != null) {
Text(text = subtitle) Text(text = subtitle)
} }
} }
IconButton(onClick = onClick) { if (showArrow) {
Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null) Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null)
} }
} }

View file

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
@ -56,6 +57,7 @@ fun RelatedMangasComfortableGrid(
header(key = "$related#content") { RelatedMangasLoadingItem() } header(key = "$related#content") { RelatedMangasLoadingItem() }
} else { } else {
val relatedManga = related as RelatedManga.Success val relatedManga = related as RelatedManga.Success
header(key = "${related.keyword}#divider") { HorizontalDivider() }
header(key = "${related.keyword}#header") { header(key = "${related.keyword}#header") {
RelatedMangaTitle( RelatedMangaTitle(
title = if (relatedManga.keyword.isNotBlank()) { title = if (relatedManga.keyword.isNotBlank()) {

View file

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
@ -56,6 +57,7 @@ fun RelatedMangasCompactGrid(
header(key = "$related#content") { RelatedMangasLoadingItem() } header(key = "$related#content") { RelatedMangasLoadingItem() }
} else { } else {
val relatedManga = related as RelatedManga.Success val relatedManga = related as RelatedManga.Success
header(key = "${related.keyword}#divider") { HorizontalDivider() }
header(key = "${related.keyword}#header") { header(key = "${related.keyword}#header") {
RelatedMangaTitle( RelatedMangaTitle(
title = if (relatedManga.keyword.isNotBlank()) { title = if (relatedManga.keyword.isNotBlank()) {

View file

@ -4,6 +4,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
@ -39,6 +40,7 @@ fun RelatedMangasList(
relatedMangas.forEach { related -> relatedMangas.forEach { related ->
val isLoading = related is RelatedManga.Loading val isLoading = related is RelatedManga.Loading
if (isLoading) { if (isLoading) {
item(key = "$related#divider") { HorizontalDivider() }
stickyHeader(key = "$related#header") { stickyHeader(key = "$related#header") {
RelatedMangaTitle( RelatedMangaTitle(
title = stringResource(MR.strings.loading), title = stringResource(MR.strings.loading),
@ -51,6 +53,7 @@ fun RelatedMangasList(
item(key = "$related#content") { RelatedMangasLoadingItem() } item(key = "$related#content") { RelatedMangasLoadingItem() }
} else { } else {
val relatedManga = related as RelatedManga.Success val relatedManga = related as RelatedManga.Success
item(key = "${related.keyword}#divider") { HorizontalDivider() }
stickyHeader(key = "${related.keyword}#header") { stickyHeader(key = "${related.keyword}#header") {
RelatedMangaTitle( RelatedMangaTitle(
title = if (relatedManga.keyword.isNotBlank()) { title = if (relatedManga.keyword.isNotBlank()) {

View file

@ -26,6 +26,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
@ -51,6 +52,7 @@ import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMap
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.browse.RelatedMangaTitle import eu.kanade.presentation.browse.RelatedMangaTitle
import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.components.relativeDateText
import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.manga.components.ChapterDownloadAction
@ -63,6 +65,7 @@ import eu.kanade.presentation.manga.components.MangaInfoBox
import eu.kanade.presentation.manga.components.MangaInfoButtons import eu.kanade.presentation.manga.components.MangaInfoButtons
import eu.kanade.presentation.manga.components.MangaToolbar import eu.kanade.presentation.manga.components.MangaToolbar
import eu.kanade.presentation.manga.components.MissingChapterCountListItem import eu.kanade.presentation.manga.components.MissingChapterCountListItem
import eu.kanade.presentation.manga.components.OutlinedButtonWithArrow
import eu.kanade.presentation.manga.components.PagePreviewItems import eu.kanade.presentation.manga.components.PagePreviewItems
import eu.kanade.presentation.manga.components.PagePreviews import eu.kanade.presentation.manga.components.PagePreviews
import eu.kanade.presentation.manga.components.RelatedMangas import eu.kanade.presentation.manga.components.RelatedMangas
@ -382,6 +385,7 @@ private fun MangaScreenSmallImpl(
// SY <-- // SY <--
// KMK --> // KMK -->
val relatedMangasEnabled = Injekt.get<SourcePreferences>().relatedMangas().get() val relatedMangasEnabled = Injekt.get<SourcePreferences>().relatedMangas().get()
val expandRelatedMangas = Injekt.get<UiPreferences>().expandRelatedTitles().get()
// KMK <-- // KMK <--
val internalOnBackPressed = { val internalOnBackPressed = {
@ -578,6 +582,8 @@ private fun MangaScreenSmallImpl(
// KMK --> // KMK -->
if (state.source !is StubSource && relatedMangasEnabled) { if (state.source !is StubSource && relatedMangasEnabled) {
if (expandRelatedMangas) {
item { HorizontalDivider() }
item( item(
key = MangaScreenItem.RELATED_TITLES, key = MangaScreenItem.RELATED_TITLES,
contentType = MangaScreenItem.RELATED_TITLES, contentType = MangaScreenItem.RELATED_TITLES,
@ -589,7 +595,7 @@ private fun MangaScreenSmallImpl(
onClick = onRelatedMangasScreenClick, onClick = onRelatedMangasScreenClick,
onLongClick = null, onLongClick = null,
) )
if (state.relatedMangasSorted == null || state.relatedMangasSorted.isNotEmpty()) { if (state.relatedMangasSorted?.isNotEmpty() != false) {
RelatedMangas( RelatedMangas(
relatedMangas = state.relatedMangasSorted, relatedMangas = state.relatedMangasSorted,
getMangaState = getMangaState, getMangaState = getMangaState,
@ -599,6 +605,18 @@ private fun MangaScreenSmallImpl(
} }
} }
} }
item { HorizontalDivider() }
} else {
item(
key = MangaScreenItem.RELATED_TITLES,
contentType = MangaScreenItem.RELATED_TITLES,
) {
OutlinedButtonWithArrow(
text = stringResource(KMR.strings.pref_source_related_mangas),
onClick = onRelatedMangasScreenClick,
)
}
}
} }
// KMK <-- // KMK <--
@ -747,6 +765,7 @@ private fun MangaScreenLargeImpl(
// SY <-- // SY <--
// KMK --> // KMK -->
val relatedMangasEnabled = Injekt.get<SourcePreferences>().relatedMangas().get() val relatedMangasEnabled = Injekt.get<SourcePreferences>().relatedMangas().get()
val expandRelatedMangas = Injekt.get<UiPreferences>().expandRelatedTitles().get()
// KMK <-- // KMK <--
val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues() val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
@ -947,6 +966,8 @@ private fun MangaScreenLargeImpl(
) { ) {
// KMK --> // KMK -->
if (state.source !is StubSource && relatedMangasEnabled) { if (state.source !is StubSource && relatedMangasEnabled) {
if (expandRelatedMangas) {
item { HorizontalDivider() }
item( item(
key = MangaScreenItem.RELATED_TITLES, key = MangaScreenItem.RELATED_TITLES,
contentType = MangaScreenItem.RELATED_TITLES, contentType = MangaScreenItem.RELATED_TITLES,
@ -958,11 +979,25 @@ private fun MangaScreenLargeImpl(
onClick = onRelatedMangasScreenClick, onClick = onRelatedMangasScreenClick,
onLongClick = null, onLongClick = null,
) )
if (state.relatedMangasSorted?.isNotEmpty() != false) {
RelatedMangas( RelatedMangas(
relatedMangas = state.relatedMangasSorted, relatedMangas = state.relatedMangasSorted,
getMangaState = getMangaState, getMangaState = getMangaState,
onMangaClick = onRelatedMangaClick, onMangaClick = onRelatedMangaClick,
onMangaLongClick = onRelatedMangaLongClick onMangaLongClick = onRelatedMangaLongClick,
)
}
}
}
item { HorizontalDivider() }
} else {
item(
key = MangaScreenItem.RELATED_TITLES,
contentType = MangaScreenItem.RELATED_TITLES,
) {
OutlinedButtonWithArrow(
text = stringResource(KMR.strings.pref_source_related_mangas),
onClick = onRelatedMangasScreenClick,
) )
} }
} }

View file

@ -0,0 +1,64 @@
package eu.kanade.presentation.manga.components
import androidx.compose.foundation.layout.Arrangement
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.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import tachiyomi.presentation.core.components.material.padding
@Composable
fun OutlinedButtonWithArrow(
text: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
icon: ImageVector = Icons.AutoMirrored.Filled.ArrowForward,
) {
OutlinedButton(
onClick = onClick,
modifier = modifier
.fillMaxWidth()
.padding(MaterialTheme.padding.small),
colors = ButtonDefaults.outlinedButtonColors(),
shape = RoundedCornerShape(8.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = text.uppercase(),
)
Spacer(modifier = Modifier.width(4.dp))
Icon(
imageVector = icon,
contentDescription = "Arrow"
)
}
}
}
@Preview(showBackground = true)
@Composable
fun OutlinedButtonWithArrowPreview() {
OutlinedButtonWithArrow(
text = "Click Me",
onClick = { /* Do nothing */ }
)
}

View file

@ -13,6 +13,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import com.materialkolor.PaletteStyle import com.materialkolor.PaletteStyle
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences import eu.kanade.domain.ui.UiPreferences
import eu.kanade.domain.ui.model.TabletUiMode import eu.kanade.domain.ui.model.TabletUiMode
import eu.kanade.domain.ui.model.ThemeMode import eu.kanade.domain.ui.model.ThemeMode
@ -196,6 +197,7 @@ object SettingsAppearanceScreen : SearchableSettings {
@Composable @Composable
fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup { fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
val previewsRowCount by uiPreferences.previewsRowCount().collectAsState() val previewsRowCount by uiPreferences.previewsRowCount().collectAsState()
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
stringResource(SYMR.strings.pref_category_fork), stringResource(SYMR.strings.pref_category_fork),
@ -204,6 +206,12 @@ object SettingsAppearanceScreen : SearchableSettings {
pref = uiPreferences.expandFilters(), pref = uiPreferences.expandFilters(),
title = stringResource(SYMR.strings.toggle_expand_search_filters), title = stringResource(SYMR.strings.toggle_expand_search_filters),
), ),
Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.expandRelatedTitles(),
title = stringResource(KMR.strings.pref_expand_related_titles),
subtitle = stringResource(KMR.strings.pref_expand_related_titles_summary),
enabled = sourcePreferences.relatedMangas().get(),
),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = uiPreferences.recommendsInOverflow(), pref = uiPreferences.recommendsInOverflow(),
title = stringResource(SYMR.strings.put_recommends_in_overflow), title = stringResource(SYMR.strings.put_recommends_in_overflow),

View file

@ -23,6 +23,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.core.net.toUri import androidx.core.net.toUri
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
@ -90,6 +91,7 @@ import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.common.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchUI import tachiyomi.core.common.util.lang.launchUI
import tachiyomi.core.common.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
@ -282,6 +284,9 @@ class MangaScreen(
// KMK --> // KMK -->
getMangaState = { screenModel.getManga(initialManga = it) }, getMangaState = { screenModel.getManga(initialManga = it) },
onRelatedMangasScreenClick = { onRelatedMangasScreenClick = {
if (successState.isRelatedMangasFetched == null) {
screenModel.screenModelScope.launchIO { screenModel.fetchRelatedMangasFromSource(onDemand = true) }
}
navigator.push( navigator.push(
RelatedMangasScreen( RelatedMangasScreen(
mangaScreenModel = screenModel, mangaScreenModel = screenModel,

View file

@ -172,8 +172,9 @@ class MangaScreenModel(
private val downloadPreferences: DownloadPreferences = Injekt.get(), private val downloadPreferences: DownloadPreferences = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(),
readerPreferences: ReaderPreferences = Injekt.get(), readerPreferences: ReaderPreferences = Injekt.get(),
uiPreferences: UiPreferences = Injekt.get(), private val uiPreferences: UiPreferences = Injekt.get(),
// KMK --> // KMK -->
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val trackPreferences: TrackPreferences = Injekt.get(), private val trackPreferences: TrackPreferences = Injekt.get(),
private val trackChapter: TrackChapter = Injekt.get(), private val trackChapter: TrackChapter = Injekt.get(),
// KMK <-- // KMK <--
@ -461,18 +462,14 @@ class MangaScreenModel(
// Fetch info-chapters when needed // Fetch info-chapters when needed
if (screenModelScope.isActive) { if (screenModelScope.isActive) {
// KMK -->
launch {
fetchRelatedMangasFromSource(onFinish = {
updateSuccessState { it.copy(isFetchingRelatedMangas = false) }
})
}
// KMK <--
val fetchFromSourceTasks = listOf( val fetchFromSourceTasks = listOf(
async { syncTrackers() }, async { syncTrackers() },
async { if (needRefreshInfo) fetchMangaFromSource() }, async { if (needRefreshInfo) fetchMangaFromSource() },
async { if (needRefreshChapter) fetchChaptersFromSource() }, async { if (needRefreshChapter) fetchChaptersFromSource() },
) )
// KMK -->
launch { fetchRelatedMangasFromSource() }
// KMK <--
fetchFromSourceTasks.awaitAll() fetchFromSourceTasks.awaitAll()
} }
@ -1115,7 +1112,7 @@ class MangaScreenModel(
val isLocal = manga.isLocal() val isLocal = manga.isLocal()
// SY --> // SY -->
val isExhManga = manga.isEhBasedManga() val isExhManga = manga.isEhBasedManga()
val enabledLanguages = Injekt.get<SourcePreferences>().enabledLanguages().get() val enabledLanguages = sourcePreferences.enabledLanguages().get()
.filterNot { it in listOf("all", "other") } .filterNot { it in listOf("all", "other") }
// SY <-- // SY <--
return map { chapter -> return map { chapter ->
@ -1219,10 +1216,26 @@ class MangaScreenModel(
} }
// KMK --> // KMK -->
/**
* Set the fetching related mangas status.
* @param state
* - false: started & fetching
* - true: finished
*/
private fun setRelatedMangasFetchedStatus(state: Boolean) {
updateSuccessState { it.copy(isRelatedMangasFetched = state) }
}
/** /**
* Requests an list of related mangas from the source. * Requests an list of related mangas from the source.
*/ */
private suspend fun fetchRelatedMangasFromSource(onFinish: () -> Unit) { internal suspend fun fetchRelatedMangasFromSource(onDemand: Boolean = false, onFinish: (() -> Unit)? = null) {
val expandRelatedTitles = uiPreferences.expandRelatedTitles().get()
if (!onDemand && !expandRelatedTitles) return
// start fetching related mangas
setRelatedMangasFetchedStatus(false)
fun exceptionHandler(e: Throwable) { fun exceptionHandler(e: Throwable) {
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
val message = with(context) { e.formattedMessage } val message = with(context) { e.formattedMessage }
@ -1232,10 +1245,10 @@ class MangaScreenModel(
} }
} }
val state = successState ?: return val state = successState ?: return
val relatedMangasEnabled = Injekt.get<SourcePreferences>().relatedMangas().get() val relatedMangasEnabled = sourcePreferences.relatedMangas().get()
try { try {
if (state.source !is StubSource) { if (state.source !is StubSource && relatedMangasEnabled) {
if (relatedMangasEnabled) {
state.source.getRelatedMangaList(state.manga.toSManga(), { e -> exceptionHandler(e) }) { pair, _ -> state.source.getRelatedMangaList(state.manga.toSManga(), { e -> exceptionHandler(e) }) { pair, _ ->
/* Push found related mangas into collection */ /* Push found related mangas into collection */
val relatedManga = RelatedManga.Success.fromPair(pair) { mangaList -> val relatedManga = RelatedManga.Success.fromPair(pair) { mangaList ->
@ -1254,11 +1267,14 @@ class MangaScreenModel(
} }
} }
} }
}
} catch (e: Exception) { } catch (e: Exception) {
exceptionHandler(e) exceptionHandler(e)
} finally { } finally {
if (onFinish != null) {
onFinish() onFinish()
} else {
setRelatedMangasFetchedStatus(true)
}
} }
} }
// KMK <-- // KMK <--
@ -1870,7 +1886,13 @@ class MangaScreenModel(
val previewsRowCount: Int, val previewsRowCount: Int,
// SY <-- // SY <--
// KMK --> // KMK -->
val isFetchingRelatedMangas: Boolean = true, /**
* status of fetching related mangas
* - null: not started
* - false: started & fetching
* - true: finished
*/
val isRelatedMangasFetched: Boolean? = null,
/** /**
* a list of <keyword, related mangas> * a list of <keyword, related mangas>
*/ */
@ -1888,8 +1910,8 @@ class MangaScreenModel(
?.sorted(manga) ?.sorted(manga)
?.removeDuplicates(manga) ?.removeDuplicates(manga)
?.filter { it.isVisible() } ?.filter { it.isVisible() }
?.isLoading(isFetchingRelatedMangas) ?.isLoading(isRelatedMangasFetched)
?: if (!isFetchingRelatedMangas) emptyList() else null ?: if (isRelatedMangasFetched == true) emptyList() else null
// KMK <-- // KMK <--
val processedChapters by lazy { val processedChapters by lazy {
@ -2051,12 +2073,8 @@ sealed interface RelatedManga {
} }
} }
internal fun List<RelatedManga>.isLoading(isFetchingRelatedMangas: Boolean): List<RelatedManga> { internal fun List<RelatedManga>.isLoading(isRelatedMangaFetched: Boolean?): List<RelatedManga> {
return if (isFetchingRelatedMangas) { return if (isRelatedMangaFetched == false) this + listOf(Loading) else this
this + listOf(Loading)
} else {
this
}
} }
} }
} }

View file

@ -12,6 +12,8 @@
<string name="pref_details_page_theme_cover_based">Details page theme based on cover</string> <string name="pref_details_page_theme_cover_based">Details page theme based on cover</string>
<string name="pref_theme_cover_based_style">Theme style</string> <string name="pref_theme_cover_based_style">Theme style</string>
<string name="pref_theme_cover_based_animate">Theme animate</string> <string name="pref_theme_cover_based_animate">Theme animate</string>
<string name="pref_expand_related_titles">Expand Related titles</string>
<string name="pref_expand_related_titles_summary">If turned off, related titles won\'t automatically load &amp; show expanded</string>
<!-- Extension section --> <!-- Extension section -->
<string name="ext_unofficial">Unofficial</string> <string name="ext_unofficial">Unofficial</string>
@ -58,7 +60,7 @@
<string name="changelogs">Change Logs</string> <string name="changelogs">Change Logs</string>
<!-- Browse settings --> <!-- Browse settings -->
<string name="pref_source_related_mangas">Related titles</string> <string name="pref_source_related_mangas">Related Titles</string>
<string name="pref_source_related_mangas_summary">Show related titles while viewing entry</string> <string name="pref_source_related_mangas_summary">Show related titles while viewing entry</string>
<string name="related_mangas_more">More like these...</string> <string name="related_mangas_more">More like these...</string>