Update Manga in Expected Period (#5734)

* Add Predict Interval Test

* Get mangas next update and interval in library update

* Get next update and interval in backup restore

* Display and set intervals, nextUpdate in Manga Info

* Move logic function to MangeScreen and InfoHeader

Update per suggestion

---------

Co-authored-by: arkon <arkon@users.noreply.github.com>
This commit is contained in:
Quang Kieu
2023-07-23 18:12:01 -04:00
committed by arkon
parent 6d69caf59e
commit cb639f4e90
14 changed files with 460 additions and 131 deletions

View File

@@ -85,6 +85,7 @@ fun MangaScreen(
state: MangaScreenModel.State.Success,
snackbarHostState: SnackbarHostState,
dateRelativeTime: Int,
intervalDisplay: () -> Pair<Int, Int>?,
dateFormat: DateFormat,
isTabletUi: Boolean,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
@@ -112,6 +113,7 @@ fun MangaScreen(
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
@@ -141,6 +143,7 @@ fun MangaScreen(
snackbarHostState = snackbarHostState,
dateRelativeTime = dateRelativeTime,
dateFormat = dateFormat,
intervalDisplay = intervalDisplay,
chapterSwipeStartAction = chapterSwipeStartAction,
chapterSwipeEndAction = chapterSwipeEndAction,
onBackClicked = onBackClicked,
@@ -160,6 +163,7 @@ fun MangaScreen(
onShareClicked = onShareClicked,
onDownloadActionClicked = onDownloadActionClicked,
onEditCategoryClicked = onEditCategoryClicked,
onEditIntervalClicked = onEditIntervalClicked,
onMigrateClicked = onMigrateClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
@@ -178,6 +182,7 @@ fun MangaScreen(
chapterSwipeStartAction = chapterSwipeStartAction,
chapterSwipeEndAction = chapterSwipeEndAction,
dateFormat = dateFormat,
intervalDisplay = intervalDisplay,
onBackClicked = onBackClicked,
onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter,
@@ -195,6 +200,7 @@ fun MangaScreen(
onShareClicked = onShareClicked,
onDownloadActionClicked = onDownloadActionClicked,
onEditCategoryClicked = onEditCategoryClicked,
onEditIntervalClicked = onEditIntervalClicked,
onMigrateClicked = onMigrateClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
@@ -214,6 +220,7 @@ private fun MangaScreenSmallImpl(
snackbarHostState: SnackbarHostState,
dateRelativeTime: Int,
dateFormat: DateFormat,
intervalDisplay: () -> Pair<Int, Int>?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit,
@@ -240,6 +247,7 @@ private fun MangaScreenSmallImpl(
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
@@ -383,10 +391,13 @@ private fun MangaScreenSmallImpl(
MangaActionRow(
favorite = state.manga.favorite,
trackingCount = state.trackingCount,
intervalDisplay = intervalDisplay,
isUserIntervalMode = state.manga.calculateInterval < 0,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onWebViewLongClicked = onWebViewLongClicked,
onTrackingClicked = onTrackingClicked,
onEditIntervalClicked = onEditIntervalClicked,
onEditCategory = onEditCategoryClicked,
)
}
@@ -440,6 +451,7 @@ fun MangaScreenLargeImpl(
snackbarHostState: SnackbarHostState,
dateRelativeTime: Int,
dateFormat: DateFormat,
intervalDisplay: () -> Pair<Int, Int>?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit,
@@ -466,6 +478,7 @@ fun MangaScreenLargeImpl(
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
@@ -596,10 +609,13 @@ fun MangaScreenLargeImpl(
MangaActionRow(
favorite = state.manga.favorite,
trackingCount = state.trackingCount,
intervalDisplay = intervalDisplay,
isUserIntervalMode = state.manga.calculateInterval < 0,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onWebViewLongClicked = onWebViewLongClicked,
onTrackingClicked = onTrackingClicked,
onEditIntervalClicked = onEditIntervalClicked,
onEditCategory = onEditCategoryClicked,
)
ExpandableMangaDescription(

View File

@@ -1,11 +1,23 @@
package eu.kanade.presentation.manga.components
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
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.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.presentation.core.components.WheelTextPicker
@Composable
fun DeleteChaptersDialog(
@@ -37,3 +49,51 @@ fun DeleteChaptersDialog(
},
)
}
@Composable
fun SetIntervalDialog(
interval: Int,
onDismissRequest: () -> Unit,
onValueChanged: (Int) -> Unit,
) {
var intervalValue by rememberSaveable { mutableIntStateOf(interval) }
AlertDialog(
onDismissRequest = onDismissRequest,
title = { Text(text = stringResource(R.string.manga_modify_calculated_interval_title)) },
text = {
BoxWithConstraints(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
val size = DpSize(width = maxWidth / 2, height = 128.dp)
val items = (0..MAX_GRACE_PERIOD).map {
if (it == 0) {
stringResource(R.string.label_default)
} else {
it.toString()
}
}
WheelTextPicker(
size = size,
items = items,
startIndex = intervalValue,
onSelectionChanged = { intervalValue = it },
)
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(R.string.action_cancel))
}
},
confirmButton = {
TextButton(onClick = {
onValueChanged(intervalValue)
onDismissRequest()
},) {
Text(text = stringResource(R.string.action_ok))
}
},
)
}

View File

@@ -25,6 +25,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.HourglassEmpty
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material.icons.outlined.AttachMoney
import androidx.compose.material.icons.outlined.Block
@@ -164,14 +165,19 @@ fun MangaActionRow(
modifier: Modifier = Modifier,
favorite: Boolean,
trackingCount: Int,
intervalDisplay: () -> Pair<Int, Int>?,
isUserIntervalMode: Boolean,
onAddToLibraryClicked: () -> Unit,
onWebViewClicked: (() -> Unit)?,
onWebViewLongClicked: (() -> Unit)?,
onTrackingClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?,
onEditCategory: (() -> Unit)?,
) {
val interval: Pair<Int, Int>? = intervalDisplay()
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
Row(modifier = modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp)) {
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
MangaActionButton(
title = if (favorite) {
stringResource(R.string.in_library)
@@ -183,6 +189,19 @@ fun MangaActionRow(
onClick = onAddToLibraryClicked,
onLongClick = onEditCategory,
)
if (onEditIntervalClicked != null && interval != null) {
MangaActionButton(
title =
if (interval.first == interval.second) {
pluralStringResource(id = R.plurals.day, count = interval.second, interval.second)
} else {
pluralStringResource(id = R.plurals.range_interval_day, count = interval.second, interval.first, interval.second)
},
icon = Icons.Default.HourglassEmpty,
color = if (isUserIntervalMode) MaterialTheme.colorScheme.primary else defaultActionButtonColor,
onClick = onEditIntervalClicked,
)
}
if (onTrackingClicked != null) {
MangaActionButton(
title = if (trackingCount == 0) {

View File

@@ -241,18 +241,15 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(R.string.pref_library_update_refresh_trackers),
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
),
// TODO: remove isDevFlavor checks once functionality is available
Preference.PreferenceItem.MultiSelectListPreference(
pref = libraryUpdateMangaRestrictionPref,
title = stringResource(R.string.pref_library_update_manga_restriction),
entries = buildMap {
put(MANGA_HAS_UNREAD, stringResource(R.string.pref_update_only_completely_read))
put(MANGA_NON_READ, stringResource(R.string.pref_update_only_started))
put(MANGA_NON_COMPLETED, stringResource(R.string.pref_update_only_non_completed))
if (isDevFlavor) {
put(MANGA_OUTSIDE_RELEASE_PERIOD, stringResource(R.string.pref_update_only_in_release_period))
}
},
entries = mapOf(
MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read),
MANGA_NON_READ to stringResource(R.string.pref_update_only_started),
MANGA_NON_COMPLETED to stringResource(R.string.pref_update_only_non_completed),
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),