show all entries going to be checked for Smart update on Upcoming screen
This commit is contained in:
parent
461d709eb1
commit
6fd67bd240
5 changed files with 189 additions and 20 deletions
|
|
@ -260,6 +260,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
status.int == trackingExtra
|
||||
}
|
||||
}
|
||||
|
||||
LibraryGroup.BY_SOURCE -> {
|
||||
val sourceExtra = groupExtra?.nullIfBlank()?.toIntOrNull()
|
||||
val source = libraryManga.map { it.manga.source }
|
||||
|
|
@ -269,12 +270,14 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
|
||||
if (source != null) libraryManga.filter { it.manga.source == source } else emptyList()
|
||||
}
|
||||
|
||||
LibraryGroup.BY_STATUS -> {
|
||||
val statusExtra = groupExtra?.toLongOrNull() ?: -1
|
||||
libraryManga.filter {
|
||||
it.manga.status == statusExtra
|
||||
}
|
||||
}
|
||||
|
||||
LibraryGroup.UNGROUPED -> libraryManga
|
||||
else -> libraryManga
|
||||
}
|
||||
|
|
@ -314,20 +317,14 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
false
|
||||
}
|
||||
|
||||
MANGA_OUTSIDE_RELEASE_PERIOD in restrictions &&
|
||||
(
|
||||
it.manga.nextUpdate > fetchWindowUpperBound ||
|
||||
// KMK -->
|
||||
MANGA_NON_COMPLETED in restrictions &&
|
||||
it.manga.status.toInt() == SManga.COMPLETED
|
||||
// KMK <--
|
||||
) -> {
|
||||
MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate > fetchWindowUpperBound -> {
|
||||
skippedUpdates.add(
|
||||
it.manga to
|
||||
context.stringResource(MR.strings.skipped_reason_not_in_release_period),
|
||||
)
|
||||
false
|
||||
}
|
||||
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
|
@ -462,6 +459,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
is SourceNotInstalledException -> context.stringResource(
|
||||
MR.strings.loader_not_implemented_error,
|
||||
)
|
||||
|
||||
else -> e.message
|
||||
}
|
||||
failedUpdates.add(manga to errorMessage)
|
||||
|
|
@ -730,7 +728,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
}
|
||||
return file
|
||||
}
|
||||
} catch (_: Exception) {}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
return File("")
|
||||
}
|
||||
|
||||
|
|
@ -755,8 +754,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
|
||||
private const val ERROR_LOG_HELP_URL = "https://mihon.app/docs/guides/troubleshooting/"
|
||||
|
||||
private const val MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 60
|
||||
|
||||
/**
|
||||
* Key for category to update.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator
|
|||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreen
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_OUTSIDE_RELEASE_PERIOD
|
||||
|
||||
class UpcomingScreen : Screen() {
|
||||
|
||||
|
|
@ -22,6 +23,11 @@ class UpcomingScreen : Screen() {
|
|||
state = state,
|
||||
setSelectedYearMonth = screenModel::setSelectedYearMonth,
|
||||
onClickUpcoming = { navigator.push(MangaScreen(it.id)) },
|
||||
// KMK -->
|
||||
showUpdatingMangas = screenModel::showUpdatingMangas,
|
||||
hideUpdatingMangas = screenModel::hideUpdatingMangas,
|
||||
isPredictReleaseDate = MANGA_OUTSIDE_RELEASE_PERIOD in screenModel.restriction,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ import androidx.compose.foundation.lazy.items
|
|||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.NewReleases
|
||||
import androidx.compose.material3.Badge
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -46,49 +48,83 @@ fun UpcomingScreenContent(
|
|||
state: UpcomingScreenModel.State,
|
||||
setSelectedYearMonth: (YearMonth) -> Unit,
|
||||
onClickUpcoming: (manga: Manga) -> Unit,
|
||||
// KMK -->
|
||||
showUpdatingMangas: () -> Unit,
|
||||
hideUpdatingMangas: () -> Unit,
|
||||
isPredictReleaseDate: Boolean,
|
||||
// KMK <--
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
// KMK -->
|
||||
val headerIndexes = if (state.isShowingUpdatingMangas) state.updatingHeaderIndexes else state.headerIndexes
|
||||
val items = if (state.isShowingUpdatingMangas) state.updatingItems else state.items
|
||||
val events = if (state.isShowingUpdatingMangas) state.updatingEvents else state.events
|
||||
// KMK <--
|
||||
|
||||
val onClickDay: (LocalDate, Int) -> Unit = { date, offset ->
|
||||
state.headerIndexes[date]?.let {
|
||||
headerIndexes[date]?.let {
|
||||
scope.launch {
|
||||
listState.animateScrollToItem(it + offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
Scaffold(
|
||||
topBar = { UpcomingToolbar() },
|
||||
topBar = {
|
||||
UpcomingToolbar(
|
||||
// KMK -->
|
||||
state.isShowingUpdatingMangas,
|
||||
showUpdatingMangas = showUpdatingMangas,
|
||||
hideUpdatingMangas = hideUpdatingMangas,
|
||||
isPredictReleaseDate = isPredictReleaseDate,
|
||||
// KMK <--
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
) { paddingValues ->
|
||||
if (isTabletUi()) {
|
||||
UpcomingScreenLargeImpl(
|
||||
listState = listState,
|
||||
items = state.items,
|
||||
events = state.events,
|
||||
items = items,
|
||||
events = events,
|
||||
paddingValues = paddingValues,
|
||||
selectedYearMonth = state.selectedYearMonth,
|
||||
setSelectedYearMonth = setSelectedYearMonth,
|
||||
onClickDay = { onClickDay(it, 0) },
|
||||
onClickUpcoming = onClickUpcoming,
|
||||
// KMK -->
|
||||
state.isShowingUpdatingMangas,
|
||||
// KMK <--
|
||||
)
|
||||
} else {
|
||||
UpcomingScreenSmallImpl(
|
||||
listState = listState,
|
||||
items = state.items,
|
||||
events = state.events,
|
||||
items = items,
|
||||
events = events,
|
||||
paddingValues = paddingValues,
|
||||
selectedYearMonth = state.selectedYearMonth,
|
||||
setSelectedYearMonth = setSelectedYearMonth,
|
||||
onClickDay = { onClickDay(it, 1) },
|
||||
onClickUpcoming = onClickUpcoming,
|
||||
// KMK -->
|
||||
state.isShowingUpdatingMangas,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UpcomingToolbar() {
|
||||
private fun UpcomingToolbar(
|
||||
// KMK -->
|
||||
isShowingUpdatingMangas: Boolean,
|
||||
showUpdatingMangas: () -> Unit,
|
||||
hideUpdatingMangas: () -> Unit,
|
||||
isPredictReleaseDate: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
|
|
@ -96,6 +132,25 @@ private fun UpcomingToolbar() {
|
|||
title = stringResource(MR.strings.label_upcoming),
|
||||
navigateUp = navigator::pop,
|
||||
actions = {
|
||||
// KMK -->
|
||||
if (isPredictReleaseDate) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
if (isShowingUpdatingMangas) {
|
||||
hideUpdatingMangas()
|
||||
} else {
|
||||
showUpdatingMangas()
|
||||
}
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.NewReleases,
|
||||
contentDescription = stringResource(MR.strings.pref_library_update_smart_update),
|
||||
tint = if (isShowingUpdatingMangas) MaterialTheme.colorScheme.primary else LocalContentColor.current,
|
||||
)
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
IconButton(onClick = { uriHandler.openUri(Constants.URL_HELP_UPCOMING) }) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
|
|
@ -143,6 +198,9 @@ private fun UpcomingScreenSmallImpl(
|
|||
setSelectedYearMonth: (YearMonth) -> Unit,
|
||||
onClickDay: (LocalDate) -> Unit,
|
||||
onClickUpcoming: (manga: Manga) -> Unit,
|
||||
// KMK -->
|
||||
isShowingUpdatingMangas: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
FastScrollLazyColumn(
|
||||
contentPadding = paddingValues,
|
||||
|
|
@ -158,7 +216,7 @@ private fun UpcomingScreenSmallImpl(
|
|||
}
|
||||
items(
|
||||
items = items,
|
||||
key = { "upcoming-${it.hashCode()}" },
|
||||
key = { (if (isShowingUpdatingMangas) "updating" else "upcoming") + it.hashCode() },
|
||||
contentType = {
|
||||
when (it) {
|
||||
is UpcomingUIModel.Header -> "header"
|
||||
|
|
@ -173,6 +231,7 @@ private fun UpcomingScreenSmallImpl(
|
|||
onClick = { onClickUpcoming(item.manga) },
|
||||
)
|
||||
}
|
||||
|
||||
is UpcomingUIModel.Header -> {
|
||||
DateHeading(
|
||||
date = item.date,
|
||||
|
|
@ -194,6 +253,9 @@ private fun UpcomingScreenLargeImpl(
|
|||
setSelectedYearMonth: (YearMonth) -> Unit,
|
||||
onClickDay: (LocalDate) -> Unit,
|
||||
onClickUpcoming: (manga: Manga) -> Unit,
|
||||
// KMK -->
|
||||
isShowingUpdatingMangas: Boolean,
|
||||
// KMK <--
|
||||
) {
|
||||
TwoPanelBox(
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
|
|
@ -209,7 +271,7 @@ private fun UpcomingScreenLargeImpl(
|
|||
FastScrollLazyColumn(state = listState) {
|
||||
items(
|
||||
items = items,
|
||||
key = { "upcoming-${it.hashCode()}" },
|
||||
key = { (if (isShowingUpdatingMangas) "updating" else "upcoming") + it.hashCode() },
|
||||
contentType = {
|
||||
when (it) {
|
||||
is UpcomingUIModel.Header -> "header"
|
||||
|
|
@ -224,6 +286,7 @@ private fun UpcomingScreenLargeImpl(
|
|||
onClick = { onClickUpcoming(item.manga) },
|
||||
)
|
||||
}
|
||||
|
||||
is UpcomingUIModel.Header -> {
|
||||
DateHeading(
|
||||
date = item.date,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.collectLatest
|
|||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import mihon.domain.upcoming.interactor.GetUpcomingManga
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
|
@ -25,6 +26,9 @@ import java.time.YearMonth
|
|||
class UpcomingScreenModel(
|
||||
private val getUpcomingManga: GetUpcomingManga = Injekt.get(),
|
||||
) : StateScreenModel<UpcomingScreenModel.State>(State()) {
|
||||
// KMK -->
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get()
|
||||
// KMK <--
|
||||
|
||||
init {
|
||||
screenModelScope.launch {
|
||||
|
|
@ -39,6 +43,18 @@ class UpcomingScreenModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
// KMK -->
|
||||
screenModelScope.launch {
|
||||
mutableState.update { state ->
|
||||
val updatingItems = getUpcomingManga.updatingMangas().toUpcomingUIModels()
|
||||
state.copy(
|
||||
updatingItems = updatingItems,
|
||||
updatingEvents = updatingItems.toEvents(),
|
||||
updatingHeaderIndexes = updatingItems.getHeaderIndexes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
}
|
||||
|
||||
private fun List<Manga>.toUpcomingUIModels(): ImmutableList<UpcomingUIModel> {
|
||||
|
|
@ -81,10 +97,36 @@ class UpcomingScreenModel(
|
|||
mutableState.update { it.copy(selectedYearMonth = yearMonth) }
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
val restriction by lazy { libraryPreferences.autoUpdateMangaRestrictions().get() }
|
||||
|
||||
fun showUpdatingMangas() {
|
||||
mutableState.update { state ->
|
||||
state.copy(
|
||||
isShowingUpdatingMangas = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun hideUpdatingMangas() {
|
||||
mutableState.update { state ->
|
||||
state.copy(
|
||||
isShowingUpdatingMangas = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
data class State(
|
||||
val selectedYearMonth: YearMonth = YearMonth.now(),
|
||||
val items: ImmutableList<UpcomingUIModel> = persistentListOf(),
|
||||
val events: ImmutableMap<LocalDate, Int> = persistentMapOf(),
|
||||
val headerIndexes: ImmutableMap<LocalDate, Int> = persistentMapOf(),
|
||||
// KMK -->
|
||||
val isShowingUpdatingMangas: Boolean = false,
|
||||
val updatingItems: ImmutableList<UpcomingUIModel> = persistentListOf(),
|
||||
val updatingEvents: ImmutableMap<LocalDate, Int> = persistentMapOf(),
|
||||
val updatingHeaderIndexes: ImmutableMap<LocalDate, Int> = persistentMapOf(),
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,28 @@
|
|||
package mihon.domain.upcoming.interactor
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_UNREAD
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_OUTSIDE_RELEASE_PERIOD
|
||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.repository.MangaRepository
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
|
||||
class GetUpcomingManga(
|
||||
private val mangaRepository: MangaRepository,
|
||||
) {
|
||||
// KMK -->
|
||||
private val libraryPreferences: LibraryPreferences = Injekt.get()
|
||||
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||
// KMK <--
|
||||
|
||||
private val includedStatuses = setOf(
|
||||
SManga.ONGOING.toLong(),
|
||||
|
|
@ -17,4 +32,50 @@ class GetUpcomingManga(
|
|||
suspend fun subscribe(): Flow<List<Manga>> {
|
||||
return mangaRepository.getUpcomingManga(includedStatuses)
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
suspend fun updatingMangas(): List<Manga> {
|
||||
val libraryManga = getLibraryManga.await()
|
||||
|
||||
val categoriesToUpdate = libraryPreferences.updateCategories().get().map(String::toLong)
|
||||
val includedManga = if (categoriesToUpdate.isNotEmpty()) {
|
||||
libraryManga.filter { it.category in categoriesToUpdate }
|
||||
} else {
|
||||
libraryManga
|
||||
}
|
||||
|
||||
val categoriesToExclude = libraryPreferences.updateCategoriesExclude().get().map { it.toLong() }
|
||||
val excludedMangaIds = if (categoriesToExclude.isNotEmpty()) {
|
||||
libraryManga.filter { it.category in categoriesToExclude }.map { it.manga.id }
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val listToUpdate = includedManga
|
||||
.filterNot { it.manga.id in excludedMangaIds }
|
||||
|
||||
val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get()
|
||||
val today = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toEpochSecond() * 1000
|
||||
|
||||
return listToUpdate
|
||||
.distinctBy { it.manga.id }
|
||||
.filter {
|
||||
when {
|
||||
it.manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE -> false
|
||||
|
||||
MANGA_NON_COMPLETED in restrictions && it.manga.status.toInt() == SManga.COMPLETED -> false
|
||||
|
||||
MANGA_HAS_UNREAD in restrictions && it.unreadCount != 0L -> false
|
||||
|
||||
MANGA_NON_READ in restrictions && it.totalChapters > 0L && !it.hasStarted -> false
|
||||
|
||||
MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate < today -> false
|
||||
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
.map { it.manga }
|
||||
.sortedBy { it.nextUpdate }
|
||||
}
|
||||
// KMK <--
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue