More refactoring of expected next update logic

This commit is contained in:
arkon
2023-07-30 19:11:20 -04:00
parent c9a1bd86b5
commit 81cd765543
14 changed files with 101 additions and 278 deletions

View File

@ -50,13 +50,14 @@ class SyncChaptersWithSource(
manga: Manga,
source: Source,
manualFetch: Boolean = false,
zoneDateTime: ZonedDateTime = ZonedDateTime.now(),
fetchRange: Pair<Long, Long> = Pair(0, 0),
fetchWindow: Pair<Long, Long> = Pair(0, 0),
): List<Chapter> {
if (rawSourceChapters.isEmpty() && !source.isLocal()) {
throw NoChaptersException()
}
val now = ZonedDateTime.now()
val sourceChapters = rawSourceChapters
.distinctBy { it.url }
.mapIndexed { i, sChapter ->
@ -138,12 +139,11 @@ class SyncChaptersWithSource(
// Return if there's nothing to add, delete or change, avoiding unnecessary db transactions.
if (toAdd.isEmpty() && toDelete.isEmpty() && toChange.isEmpty()) {
if (manualFetch || manga.fetchInterval == 0 || manga.nextUpdate < fetchRange.first) {
if (manualFetch || manga.fetchInterval == 0 || manga.nextUpdate < fetchWindow.first) {
updateManga.awaitUpdateFetchInterval(
manga,
dbChapters,
zoneDateTime,
fetchRange,
now,
fetchWindow,
)
}
return emptyList()
@ -200,8 +200,7 @@ class SyncChaptersWithSource(
val chapterUpdates = toChange.map { it.toChapterUpdate() }
updateChapter.awaitAll(chapterUpdates)
}
val newChapters = chapterRepository.getChapterByMangaId(manga.id)
updateManga.awaitUpdateFetchInterval(manga, newChapters, zoneDateTime, fetchRange)
updateManga.awaitUpdateFetchInterval(manga, now, fetchWindow)
// Set this manga as updated since chapters were changed
// Note that last_update actually represents last time the chapter list changed at all

View File

@ -3,7 +3,6 @@ package eu.kanade.domain.manga.interactor
import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.source.model.SManga
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.interactor.SetFetchInterval
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaUpdate
@ -79,16 +78,12 @@ class UpdateManga(
suspend fun awaitUpdateFetchInterval(
manga: Manga,
chapters: List<Chapter>,
zonedDateTime: ZonedDateTime = ZonedDateTime.now(),
fetchRange: Pair<Long, Long> = setFetchInterval.getCurrent(zonedDateTime),
dateTime: ZonedDateTime = ZonedDateTime.now(),
window: Pair<Long, Long> = setFetchInterval.getWindow(dateTime),
): Boolean {
val updatedManga = setFetchInterval.update(manga, chapters, zonedDateTime, fetchRange)
return if (updatedManga != null) {
mangaRepository.update(updatedManga)
} else {
true
}
return setFetchInterval.toMangaUpdateOrNull(manga, dateTime, window)
?.let { mangaRepository.update(it) }
?: false
}
suspend fun awaitUpdateLastUpdate(mangaId: Long): Boolean {

View File

@ -62,7 +62,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.getNameForMangaInfo
import eu.kanade.tachiyomi.ui.manga.ChapterItem
import eu.kanade.tachiyomi.ui.manga.FetchInterval
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
import eu.kanade.tachiyomi.util.lang.toRelativeString
import eu.kanade.tachiyomi.util.system.copyToClipboard
@ -85,7 +84,7 @@ import java.util.Date
fun MangaScreen(
state: MangaScreenModel.State.Success,
snackbarHostState: SnackbarHostState,
fetchInterval: FetchInterval?,
fetchInterval: Int?,
dateFormat: DateFormat,
isTabletUi: Boolean,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
@ -217,7 +216,7 @@ private fun MangaScreenSmallImpl(
state: MangaScreenModel.State.Success,
snackbarHostState: SnackbarHostState,
dateFormat: DateFormat,
fetchInterval: FetchInterval?,
fetchInterval: Int?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit,
@ -448,7 +447,7 @@ fun MangaScreenLargeImpl(
state: MangaScreenModel.State.Success,
snackbarHostState: SnackbarHostState,
dateFormat: DateFormat,
fetchInterval: FetchInterval?,
fetchInterval: Int?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit,

View File

@ -16,7 +16,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import eu.kanade.tachiyomi.R
import tachiyomi.domain.manga.interactor.MAX_GRACE_PERIOD
import tachiyomi.domain.manga.interactor.MAX_FETCH_INTERVAL
import tachiyomi.presentation.core.components.WheelTextPicker
@Composable
@ -56,7 +56,7 @@ fun SetIntervalDialog(
onDismissRequest: () -> Unit,
onValueChanged: (Int) -> Unit,
) {
var intervalValue by rememberSaveable { mutableIntStateOf(interval) }
var selectedInterval by rememberSaveable { mutableIntStateOf(if (interval < 0) -interval else 0) }
AlertDialog(
onDismissRequest = onDismissRequest,
@ -67,7 +67,7 @@ fun SetIntervalDialog(
contentAlignment = Alignment.Center,
) {
val size = DpSize(width = maxWidth / 2, height = 128.dp)
val items = (0..MAX_GRACE_PERIOD).map {
val items = (0..MAX_FETCH_INTERVAL).map {
if (it == 0) {
stringResource(R.string.label_default)
} else {
@ -77,8 +77,8 @@ fun SetIntervalDialog(
WheelTextPicker(
size = size,
items = items,
startIndex = intervalValue,
onSelectionChanged = { intervalValue = it },
startIndex = selectedInterval,
onSelectionChanged = { selectedInterval = it },
)
}
},
@ -89,7 +89,7 @@ fun SetIntervalDialog(
},
confirmButton = {
TextButton(onClick = {
onValueChanged(intervalValue)
onValueChanged(selectedInterval)
onDismissRequest()
},) {
Text(text = stringResource(R.string.action_ok))

View File

@ -78,13 +78,13 @@ import coil.compose.AsyncImage
import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.manga.FetchInterval
import eu.kanade.tachiyomi.util.system.copyToClipboard
import tachiyomi.domain.manga.model.Manga
import tachiyomi.presentation.core.components.material.TextButton
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.util.clickableNoIndication
import tachiyomi.presentation.core.util.secondaryItemAlpha
import kotlin.math.absoluteValue
import kotlin.math.roundToInt
private val whitespaceLineRegex = Regex("[\\r\\n]{2,}", setOf(RegexOption.MULTILINE))
@ -166,7 +166,7 @@ fun MangaActionRow(
modifier: Modifier = Modifier,
favorite: Boolean,
trackingCount: Int,
fetchInterval: FetchInterval?,
fetchInterval: Int?,
isUserIntervalMode: Boolean,
onAddToLibraryClicked: () -> Unit,
onWebViewClicked: (() -> Unit)?,
@ -190,14 +190,8 @@ fun MangaActionRow(
onLongClick = onEditCategory,
)
if (onEditIntervalClicked != null && fetchInterval != null) {
val intervalPair = 1.coerceAtLeast(fetchInterval.interval - fetchInterval.leadDays) to (fetchInterval.interval + fetchInterval.followDays)
MangaActionButton(
title =
if (intervalPair.first == intervalPair.second) {
pluralStringResource(id = R.plurals.day, count = intervalPair.second, intervalPair.second)
} else {
pluralStringResource(id = R.plurals.range_interval_day, count = intervalPair.second, intervalPair.first, intervalPair.second)
},
title = pluralStringResource(id = R.plurals.day, count = fetchInterval.absoluteValue, fetchInterval.absoluteValue),
icon = Icons.Default.HourglassEmpty,
color = if (isUserIntervalMode) MaterialTheme.colorScheme.primary else defaultActionButtonColor,
onClick = onEditIntervalClicked,

View File

@ -1,33 +1,18 @@
package eu.kanade.presentation.more.settings.screen
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastMap
import androidx.core.content.ContextCompat
import cafe.adriel.voyager.navigator.LocalNavigator
@ -54,8 +39,6 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_U
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.MAX_GRACE_PERIOD
import tachiyomi.presentation.core.components.WheelTextPicker
import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -141,13 +124,10 @@ object SettingsLibraryScreen : SearchableSettings {
val context = LocalContext.current
val libraryUpdateIntervalPref = libraryPreferences.libraryUpdateInterval()
val libraryUpdateDeviceRestrictionPref = libraryPreferences.libraryUpdateDeviceRestriction()
val libraryUpdateMangaRestrictionPref = libraryPreferences.libraryUpdateMangaRestriction()
val libraryUpdateCategoriesPref = libraryPreferences.libraryUpdateCategories()
val libraryUpdateCategoriesExcludePref = libraryPreferences.libraryUpdateCategoriesExclude()
val libraryUpdateInterval by libraryUpdateIntervalPref.collectAsState()
val libraryUpdateMangaRestriction by libraryUpdateMangaRestrictionPref.collectAsState()
val included by libraryUpdateCategoriesPref.collectAsState()
val excluded by libraryUpdateCategoriesExcludePref.collectAsState()
@ -168,25 +148,10 @@ object SettingsLibraryScreen : SearchableSettings {
},
)
}
val leadRange by libraryPreferences.leadingExpectedDays().collectAsState()
val followRange by libraryPreferences.followingExpectedDays().collectAsState()
var showFetchRangesDialog by rememberSaveable { mutableStateOf(false) }
if (showFetchRangesDialog) {
LibraryExpectedRangeDialog(
initialLead = leadRange,
initialFollow = followRange,
onDismissRequest = { showFetchRangesDialog = false },
onValueChanged = { leadValue, followValue ->
libraryPreferences.leadingExpectedDays().set(leadValue)
libraryPreferences.followingExpectedDays().set(followValue)
showFetchRangesDialog = false
},
)
}
return Preference.PreferenceGroup(
title = stringResource(R.string.pref_category_library_update),
preferenceItems = listOfNotNull(
preferenceItems = listOf(
Preference.PreferenceItem.ListPreference(
pref = libraryUpdateIntervalPref,
title = stringResource(R.string.pref_library_update_interval),
@ -204,7 +169,7 @@ object SettingsLibraryScreen : SearchableSettings {
},
),
Preference.PreferenceItem.MultiSelectListPreference(
pref = libraryUpdateDeviceRestrictionPref,
pref = libraryPreferences.libraryUpdateDeviceRestriction(),
enabled = libraryUpdateInterval > 0,
title = stringResource(R.string.pref_library_update_restriction),
subtitle = stringResource(R.string.restrictions),
@ -241,7 +206,7 @@ object SettingsLibraryScreen : SearchableSettings {
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
),
Preference.PreferenceItem.MultiSelectListPreference(
pref = libraryUpdateMangaRestrictionPref,
pref = libraryPreferences.libraryUpdateMangaRestriction(),
title = stringResource(R.string.pref_library_update_manga_restriction),
entries = mapOf(
MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read),
@ -250,17 +215,6 @@ object SettingsLibraryScreen : SearchableSettings {
MANGA_OUTSIDE_RELEASE_PERIOD to stringResource(R.string.pref_update_only_in_release_period),
),
),
Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_update_release_grace_period),
subtitle = listOf(
pluralStringResource(R.plurals.pref_update_release_leading_days, leadRange, leadRange),
pluralStringResource(R.plurals.pref_update_release_following_days, followRange, followRange),
).joinToString(),
onClick = { showFetchRangesDialog = true },
).takeIf { MANGA_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction },
Preference.PreferenceItem.InfoPreference(
title = stringResource(R.string.pref_update_release_grace_period_info),
).takeIf { MANGA_OUTSIDE_RELEASE_PERIOD in libraryUpdateMangaRestriction },
Preference.PreferenceItem.SwitchPreference(
pref = libraryPreferences.newShowUpdatesCount(),
title = stringResource(R.string.pref_library_update_show_tab_badge),
@ -299,79 +253,4 @@ object SettingsLibraryScreen : SearchableSettings {
),
)
}
@Composable
private fun LibraryExpectedRangeDialog(
initialLead: Int,
initialFollow: Int,
onDismissRequest: () -> Unit,
onValueChanged: (portrait: Int, landscape: Int) -> Unit,
) {
var leadValue by rememberSaveable { mutableIntStateOf(initialLead) }
var followValue by rememberSaveable { mutableIntStateOf(initialFollow) }
AlertDialog(
onDismissRequest = onDismissRequest,
title = { Text(text = stringResource(R.string.pref_update_release_grace_period)) },
text = {
Column {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
modifier = Modifier.weight(1f),
text = pluralStringResource(R.plurals.pref_update_release_leading_days, leadValue, leadValue),
textAlign = TextAlign.Center,
maxLines = 1,
style = MaterialTheme.typography.labelMedium,
)
Text(
modifier = Modifier.weight(1f),
text = pluralStringResource(R.plurals.pref_update_release_following_days, followValue, followValue),
textAlign = TextAlign.Center,
maxLines = 1,
style = MaterialTheme.typography.labelMedium,
)
}
}
BoxWithConstraints(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
val size = DpSize(width = maxWidth / 2, height = 128.dp)
val items = (0..MAX_GRACE_PERIOD).map(Int::toString)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
WheelTextPicker(
size = size,
items = items,
startIndex = leadValue,
onSelectionChanged = {
leadValue = it
},
)
WheelTextPicker(
size = size,
items = items,
startIndex = followValue,
onSelectionChanged = {
followValue = it
},
)
}
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(android.R.string.cancel))
}
},
confirmButton = {
TextButton(onClick = { onValueChanged(leadValue, followValue) }) {
Text(text = stringResource(R.string.action_ok))
}
},
)
}
}

View File

@ -33,8 +33,8 @@ class BackupRestorer(
private val chapterRepository: ChapterRepository = Injekt.get()
private val setFetchInterval: SetFetchInterval = Injekt.get()
private var zonedDateTime = ZonedDateTime.now()
private var currentFetchInterval = setFetchInterval.getCurrent(zonedDateTime)
private var now = ZonedDateTime.now()
private var currentFetchWindow = setFetchInterval.getWindow(now)
private var backupManager = BackupManager(context)
@ -102,8 +102,8 @@ class BackupRestorer(
// Store source mapping for error messages
val backupMaps = backup.backupBrokenSources.map { BackupSource(it.name, it.sourceId) } + backup.backupSources
sourceMapping = backupMaps.associate { it.sourceId to it.name }
zonedDateTime = ZonedDateTime.now()
currentFetchInterval = setFetchInterval.getCurrent(zonedDateTime)
now = ZonedDateTime.now()
currentFetchWindow = setFetchInterval.getWindow(now)
return coroutineScope {
// Restore individual manga
@ -146,8 +146,7 @@ class BackupRestorer(
// Fetch rest of manga information
restoreNewManga(updatedManga, chapters, categories, history, tracks, backupCategories)
}
val updatedChapters = chapterRepository.getChapterByMangaId(restoredManga.id)
updateManga.awaitUpdateFetchInterval(restoredManga, updatedChapters, zonedDateTime, currentFetchInterval)
updateManga.awaitUpdateFetchInterval(restoredManga, now, currentFetchWindow)
} catch (e: Exception) {
val sourceName = sourceMapping[manga.source] ?: manga.source.toString()
errors.add(Date() to "${manga.title} [$sourceName]: ${e.message}")

View File

@ -231,9 +231,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val hasDownloads = AtomicBoolean(false)
val restrictions = libraryPreferences.libraryUpdateMangaRestriction().get()
val now = ZonedDateTime.now()
val fetchInterval = setFetchInterval.getCurrent(now)
val higherLimit = fetchInterval.second
val fetchWindow by lazy { setFetchInterval.getWindow(ZonedDateTime.now()) }
coroutineScope {
mangaToUpdate.groupBy { it.manga.source }.values
@ -255,8 +253,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
manga,
) {
when {
MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && manga.nextUpdate > higherLimit ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_in_release_period))
manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_always_update))
MANGA_NON_COMPLETED in restrictions && manga.status.toInt() == SManga.COMPLETED ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_completed))
@ -267,12 +265,12 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
MANGA_NON_READ in restrictions && libraryManga.totalChapters > 0L && !libraryManga.hasStarted ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_started))
manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_always_update))
MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && manga.nextUpdate !in fetchWindow.first.rangeTo(fetchWindow.second) ->
skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_in_release_period))
else -> {
try {
val newChapters = updateManga(manga, now, fetchInterval)
val newChapters = updateManga(manga, fetchWindow)
.sortedByDescending { it.sourceOrder }
if (newChapters.isNotEmpty()) {
@ -328,6 +326,13 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
)
}
if (skippedUpdates.isNotEmpty()) {
// TODO: surface skipped reasons to user
logcat {
skippedUpdates
.groupBy { it.second }
.map { (reason, entries) -> "$reason: [${entries.map { it.first.title }.sorted().joinToString()}]" }
.joinToString()
}
notifier.showUpdateSkippedNotification(skippedUpdates.size)
}
}
@ -344,7 +349,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
* @param manga the manga to update.
* @return a pair of the inserted and removed chapters.
*/
private suspend fun updateManga(manga: Manga, zoneDateTime: ZonedDateTime, fetchRange: Pair<Long, Long>): List<Chapter> {
private suspend fun updateManga(manga: Manga, fetchWindow: Pair<Long, Long>): List<Chapter> {
val source = sourceManager.getOrStub(manga.source)
// Update manga metadata if needed
@ -359,7 +364,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
// to get latest data so it doesn't get overwritten later on
val dbManga = getManga.await(manga.id)?.takeIf { it.favorite } ?: return emptyList()
return syncChaptersWithSource.await(chapters, dbManga, source, false, zoneDateTime, fetchRange)
return syncChaptersWithSource.await(chapters, dbManga, source, false, fetchWindow)
}
private suspend fun updateCovers() {

View File

@ -83,13 +83,6 @@ class MangaScreen(
val successState = state as MangaScreenModel.State.Success
val isHttpSource = remember { successState.source is HttpSource }
val fetchInterval = remember(successState.manga.fetchInterval) {
FetchInterval(
interval = successState.manga.fetchInterval,
leadDays = screenModel.leadDay,
followDays = screenModel.followDay,
)
}
LaunchedEffect(successState.manga, screenModel.source) {
if (isHttpSource) {
@ -107,7 +100,7 @@ class MangaScreen(
state = successState,
snackbarHostState = screenModel.snackbarHostState,
dateFormat = screenModel.dateFormat,
fetchInterval = fetchInterval,
fetchInterval = successState.manga.fetchInterval,
isTabletUi = isTabletUi(),
chapterSwipeStartAction = screenModel.chapterSwipeStartAction,
chapterSwipeEndAction = screenModel.chapterSwipeEndAction,
@ -218,7 +211,7 @@ class MangaScreen(
}
is MangaScreenModel.Dialog.SetFetchInterval -> {
SetIntervalDialog(
interval = if (dialog.manga.fetchInterval < 0) -dialog.manga.fetchInterval else 0,
interval = dialog.manga.fetchInterval,
onDismissRequest = onDismissRequest,
onValueChanged = { screenModel.setFetchInterval(dialog.manga, it) },
)

View File

@ -129,8 +129,6 @@ class MangaScreenModel(
private val skipFiltered by readerPreferences.skipFiltered().asState(coroutineScope)
val isUpdateIntervalEnabled = LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.libraryUpdateMangaRestriction().get()
val leadDay = libraryPreferences.leadingExpectedDays().get()
val followDay = libraryPreferences.followingExpectedDays().get()
private val selectedPositions: Array<Int> = arrayOf(-1, -1) // first and last selected index in list
private val selectedChapterIds: HashSet<Long> = HashSet()
@ -361,20 +359,14 @@ class MangaScreenModel(
}
}
fun setFetchInterval(manga: Manga, newInterval: Int) {
val interval = when (newInterval) {
// reset interval 0 default to trigger recalculation
// only reset if interval is custom, which is negative
0 -> if (manga.fetchInterval < 0) 0 else manga.fetchInterval
else -> -newInterval
}
fun setFetchInterval(manga: Manga, interval: Int) {
coroutineScope.launchIO {
updateManga.awaitUpdateFetchInterval(
manga.copy(fetchInterval = interval),
successState?.chapters?.map { it.chapter }.orEmpty(),
// Custom intervals are negative
manga.copy(fetchInterval = -interval),
)
val newManga = mangaRepository.getMangaById(mangaId)
updateSuccessState { it.copy(manga = newManga) }
val updatedManga = mangaRepository.getMangaById(manga.id)
updateSuccessState { it.copy(manga = updatedManga) }
}
}
@ -1055,10 +1047,3 @@ data class ChapterItem(
) {
val isDownloaded = downloadState == Download.State.DOWNLOADED
}
@Immutable
data class FetchInterval(
val interval: Int,
val leadDays: Int,
val followDays: Int,
)