From 8d659917595edce3bdd0f5bff2e6f22448bb206d Mon Sep 17 00:00:00 2001 From: manav_chaudhary <100396248+manavchaudhary1@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:28:15 +0530 Subject: [PATCH] feat(library): Added a button to refresh selected manga entries (#1038) * feat: add refresh button to MangaBottomActionMenu * feat: add refresh functionality for selected manga in LibraryTab * feat: add refreshSelectedManga function to update selected mangas * feat: add targeted update functionality for specific manga IDs * Update CHANGELOG.md * Refactoring & cleanup * Move it to overflow menu * Optimize update logic * Fix index & improve code * Remove parentheses --------- Co-authored-by: Cuong-Tran --- .../manga/components/MangaBottomActionMenu.kt | 13 ++++++- .../data/library/LibraryUpdateJob.kt | 34 +++++++++++++++++++ .../ui/library/LibraryScreenModel.kt | 15 ++++++++ .../kanade/tachiyomi/ui/library/LibraryTab.kt | 14 ++++++++ .../moko-resources/base/strings.xml | 2 ++ 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt index 35274bf4e..8efe9ebb3 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt @@ -66,6 +66,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import tachiyomi.i18n.MR +import tachiyomi.i18n.kmk.KMR import tachiyomi.i18n.sy.SYMR import tachiyomi.presentation.core.i18n.stringResource import kotlin.time.Duration.Companion.seconds @@ -266,8 +267,9 @@ fun LibraryBottomActionMenu( // SY <-- // KMK --> onClickMerge: (() -> Unit)?, - // KMK <-- modifier: Modifier = Modifier, + onClickRefreshSelected: (() -> Unit)? = null, + // KMK <-- ) { AnimatedVisibility( visible = visible, @@ -302,6 +304,7 @@ fun LibraryBottomActionMenu( // KMK --> onClickMigrate != null || onClickMerge != null || + onClickRefreshSelected != null || // KMK <-- onClickCollectRecommendations != null val configuration = LocalConfiguration.current @@ -399,6 +402,14 @@ fun LibraryBottomActionMenu( offset = DpOffset((-10).dp, 0.dp), // KMK <-- ) { + // KMK --> + if (onClickRefreshSelected != null) { + DropdownMenuItem( + text = { Text(stringResource(KMR.strings.action_update)) }, + onClick = onClickRefreshSelected, + ) + } + // KMK <-- if (!isTabletUi) { if (onClickMigrate != null) { DropdownMenuItem( diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index 54eab515f..c1bb1763f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -230,6 +230,27 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet val groupLibraryUpdateType = libraryPreferences.groupLibraryUpdateType().get() // SY <-- + // KMK --> + // Check if specific manga IDs are provided for targeted update + val targetMangaIds = inputData.getLongArray(KEY_MANGA_IDS)?.toSet() + if (targetMangaIds != null) { + // Filter to only the specified manga IDs + mangaToUpdate = libraryManga + .filter { + it.manga.id in targetMangaIds && + when { + // Apply update restrictions even for targeted updates + it.manga.updateStrategy == UpdateStrategy.ONLY_FETCH_ONCE && it.totalChapters > 0L -> false + // Skip other restrictions for targeted updates to allow forced refresh + else -> true + } + } + + notifier.showQueueSizeWarningNotificationIfNeeded(mangaToUpdate) + return + } + // KMK <-- + val listToUpdate = if (categoryId != -1L) { libraryManga.filter { it.category == categoryId } } else if ( @@ -724,6 +745,13 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet const val KEY_GROUP_EXTRA = "group_extra" // SY <-- + // KMK --> + /** + * Key for specific manga IDs to update. + */ + private const val KEY_MANGA_IDS = "manga_ids" + // KMK <-- + fun cancelAllWorks(context: Context) { context.workManager.cancelAllWorkByTag(TAG) } @@ -785,6 +813,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet group: Int = LibraryGroup.BY_DEFAULT, groupExtra: String? = null, // SY <-- + // KMK --> + mangaIds: List? = null, + // KMK <-- ): Boolean { val wm = context.workManager // Check if the LibraryUpdateJob is already running @@ -800,6 +831,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet KEY_GROUP to group, KEY_GROUP_EXTRA to groupExtra, // SY <-- + // KMK --> + KEY_MANGA_IDS to mangaIds?.toLongArray(), + // KMK <-- ) val syncPreferences: SyncPreferences = Injekt.get() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 3f3d872ac..84d762cc7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -30,6 +30,7 @@ import eu.kanade.presentation.manga.DownloadAction import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadManager +import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.track.TrackStatus import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.source.Source @@ -932,6 +933,20 @@ class LibraryScreenModel( } // SY <-- + // KMK --> + /** + * Update Selected Mangas + */ + fun refreshSelectedManga(): Boolean { + val mangaIds = state.value.selection.map { it.manga.id } + return LibraryUpdateJob.startNow( + context = preferences.context, + mangaIds = mangaIds, + target = LibraryUpdateJob.Target.CHAPTERS, + ) + } + // KMK <-- + /** * Marks mangas' chapters read status. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt index 24fd2ecee..7cbc35a5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt @@ -261,6 +261,20 @@ data object LibraryTab : Tab { context.toast(SYMR.strings.no_valid_entry) } }, + onClickRefreshSelected = { + val started = screenModel.refreshSelectedManga() + scope.launch { + val msgRes = if (started) { + KMR.strings.updating + } else { + MR.strings.update_already_running + } + snackbarHostState.showSnackbar(context.stringResource(msgRes)) + if (started) { + screenModel.clearSelection() + } + } + }, // KMK <-- ) }, diff --git a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml index 1c07a31db..adf211723 100644 --- a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml +++ b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml @@ -15,6 +15,7 @@ Show hidden categories Panorama cover Open folder + Update Copy first page to clipboard @@ -78,6 +79,7 @@ Source icon Use language icon Entries in excluded categories will not be shown even if they are also in included categories. + Updating Refresh extension page to update list. More extensions...