From b1820a018482a5c183aa900c3cbadb9d920d0c81 Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Thu, 29 Aug 2024 02:54:44 -0700 Subject: [PATCH 1/4] Add advanced Library setting to allow library manga's titles to update from source --- .../domain/manga/interactor/UpdateManga.kt | 20 +++++++++++--- .../settings/screen/SettingsAdvancedScreen.kt | 13 +++++++-- .../data/download/DownloadManager.kt | 27 +++++++++++++++++++ .../data/library/LibraryUpdateJob.kt | 2 +- .../tachiyomi/ui/manga/MangaScreenModel.kt | 2 +- .../library/service/LibraryPreferences.kt | 2 ++ .../moko-resources/base/strings.xml | 2 ++ 7 files changed, 61 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt index d5cfc248dd..1af789b126 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt @@ -2,7 +2,10 @@ package eu.kanade.domain.manga.interactor import eu.kanade.domain.manga.model.hasCustomCover import eu.kanade.tachiyomi.data.cache.CoverCache +import eu.kanade.tachiyomi.data.download.DownloadManager +import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.SManga +import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.FetchInterval import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.MangaUpdate @@ -27,10 +30,13 @@ class UpdateManga( } suspend fun awaitUpdateFromSource( + source: Source, localManga: Manga, remoteManga: SManga, manualFetch: Boolean, coverCache: CoverCache = Injekt.get(), + libraryPreferences: LibraryPreferences = Injekt.get(), + downloadManager: DownloadManager = Injekt.get() ): Boolean { val remoteTitle = try { remoteManga.title @@ -38,8 +44,12 @@ class UpdateManga( "" } - // if the manga isn't a favorite, set its title from source and update in db - val title = if (remoteTitle.isEmpty() || localManga.favorite) null else remoteTitle + // if the manga isn't a favorite (or 'update titles' preference is enabled), set its title from source and update in db + val title = + if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles().get())) + remoteTitle + else + null val coverLastModified = when { @@ -59,7 +69,7 @@ class UpdateManga( val thumbnailUrl = remoteManga.thumbnail_url?.takeIf { it.isNotEmpty() } - return mangaRepository.update( + val success = mangaRepository.update( MangaUpdate( id = localManga.id, title = title, @@ -74,6 +84,10 @@ class UpdateManga( initialized = true, ), ) + if (success && title != null) { + downloadManager.renameManga(source, localManga, title) + } + return success; } suspend fun awaitUpdateFetchInterval( diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index 89f53bc39b..d532d7e7b8 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -63,6 +63,7 @@ import okhttp3.Headers import tachiyomi.core.common.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.withUIContext import tachiyomi.core.common.util.system.logcat +import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.ResetViewerFlags import tachiyomi.i18n.MR import tachiyomi.presentation.core.i18n.stringResource @@ -85,6 +86,7 @@ object SettingsAdvancedScreen : SearchableSettings { val basePreferences = remember { Injekt.get() } val networkPreferences = remember { Injekt.get() } + val libraryPreferences = remember { Injekt.get() } return listOf( Preference.PreferenceItem.TextPreference( @@ -125,7 +127,7 @@ object SettingsAdvancedScreen : SearchableSettings { getBackgroundActivityGroup(), getDataGroup(), getNetworkGroup(networkPreferences = networkPreferences), - getLibraryGroup(), + getLibraryGroup(libraryPreferences = libraryPreferences), getReaderGroup(basePreferences = basePreferences), getExtensionsGroup(basePreferences = basePreferences), ) @@ -286,7 +288,9 @@ object SettingsAdvancedScreen : SearchableSettings { } @Composable - private fun getLibraryGroup(): Preference.PreferenceGroup { + private fun getLibraryGroup( + libraryPreferences: LibraryPreferences + ): Preference.PreferenceGroup { val scope = rememberCoroutineScope() val context = LocalContext.current @@ -314,6 +318,11 @@ object SettingsAdvancedScreen : SearchableSettings { } }, ), + Preference.PreferenceItem.SwitchPreference( + pref = libraryPreferences.updateMangaTitles(), + title = stringResource(MR.strings.pref_update_library_manga_titles), + subtitle = stringResource(MR.strings.pref_update_library_manga_titles_summary), + ), ), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 5fba899ca3..9fe50e463e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -327,6 +327,33 @@ class DownloadManager( } } + /** + * Renames manga download folder + * + * @param source the source of the manga. + * @param manga the manga to rename + * @param newTitle the new manga title. + */ + fun renameManga(source: Source, manga: Manga, newTitle: String) { + val oldFolder = provider.findMangaDir(manga.title, source) ?: return + val newName = provider.getMangaDirName(newTitle) + + if (oldFolder.name == newName) return + + val capitalizationChanged = oldFolder.name.equals(newName, ignoreCase = true) + if (capitalizationChanged) { + val tempName = newName + Downloader.TMP_DIR_SUFFIX + if (!oldFolder.renameTo(tempName)) { + logcat(LogPriority.ERROR) { "Failed to rename manga download folder: ${oldFolder.name}" } + return + } + } + + if (!oldFolder.renameTo(newName)) { + logcat(LogPriority.ERROR) { "Failed to rename manga download folder: ${oldFolder.name}" } + } + } + /** * Renames an already downloaded chapter * 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 6f3cfe0d8a..531564adb2 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 @@ -340,7 +340,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet // Update manga metadata if needed if (libraryPreferences.autoUpdateMetadata().get()) { val networkManga = source.getMangaDetails(manga.toSManga()) - updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache) + updateManga.awaitUpdateFromSource(source, manga, networkManga, manualFetch = false, coverCache) } val chapters = source.getChapterList(manga.toSManga()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 53665552db..b87b33d3ab 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -270,7 +270,7 @@ class MangaScreenModel( try { withIOContext { val networkManga = state.source.getMangaDetails(state.manga.toSManga()) - updateManga.awaitUpdateFromSource(state.manga, networkManga, manualFetch) + updateManga.awaitUpdateFromSource(state.source, state.manga, networkManga, manualFetch) } } catch (e: Throwable) { // Ignore early hints "errors" that aren't handled by OkHttp diff --git a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt index 5a9d86182f..e903d5e229 100644 --- a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt @@ -188,6 +188,8 @@ class LibraryPreferences( ChapterSwipeAction.ToggleRead, ) + fun updateMangaTitles() = preferenceStore.getBoolean("pref_update_library_manga_titles", false) + // endregion enum class ChapterSwipeAction { diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index a07f533daf..5ffdc3dd8a 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -614,6 +614,8 @@ Verbose logging Print verbose logs to system log (reduces app performance) Debug info + Allow title changes for library entries + If a source has a different title for an entry than the one stored in the library, update it to match the source\'s title. Website From c0b9183fe52833842890da33528164ac30e0df3d Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Sun, 24 Nov 2024 02:20:07 -0800 Subject: [PATCH 2/4] Update UpdateManga.kt --- .../java/eu/kanade/domain/manga/interactor/UpdateManga.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt index 1af789b126..2e98704c1a 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt @@ -36,7 +36,7 @@ class UpdateManga( manualFetch: Boolean, coverCache: CoverCache = Injekt.get(), libraryPreferences: LibraryPreferences = Injekt.get(), - downloadManager: DownloadManager = Injekt.get() + downloadManager: DownloadManager = Injekt.get(), ): Boolean { val remoteTitle = try { remoteManga.title @@ -87,7 +87,7 @@ class UpdateManga( if (success && title != null) { downloadManager.renameManga(source, localManga, title) } - return success; + return success } suspend fun awaitUpdateFetchInterval( From 7806ef04509454071e39a37bd0ee9efe202e4d1d Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Sun, 24 Nov 2024 02:20:30 -0800 Subject: [PATCH 3/4] Update SettingsAdvancedScreen.kt --- .../presentation/more/settings/screen/SettingsAdvancedScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index d532d7e7b8..dfd33e364b 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -289,7 +289,7 @@ object SettingsAdvancedScreen : SearchableSettings { @Composable private fun getLibraryGroup( - libraryPreferences: LibraryPreferences + libraryPreferences: LibraryPreferences, ): Preference.PreferenceGroup { val scope = rememberCoroutineScope() val context = LocalContext.current From 8f6e3b9f6432828493a75a7aee4d9c1ed0449d8a Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Sun, 24 Nov 2024 02:21:50 -0800 Subject: [PATCH 4/4] Update UpdateManga.kt --- .../java/eu/kanade/domain/manga/interactor/UpdateManga.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt index 2e98704c1a..106432aca1 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt @@ -46,10 +46,11 @@ class UpdateManga( // if the manga isn't a favorite (or 'update titles' preference is enabled), set its title from source and update in db val title = - if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles().get())) + if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles().get())) { remoteTitle - else + } else { null + } val coverLastModified = when {