From f5e714f794fa78dc5b6ee4292a34aaff18501ded Mon Sep 17 00:00:00 2001 From: FlaminSarge Date: Thu, 8 May 2025 15:09:32 -0700 Subject: [PATCH] Add advanced option to always update manga title from source (#1182) Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> (cherry picked from commit 8b45ef0e5d5d368e0925df9816ae423defaed4d9) # Conflicts: # CHANGELOG.md # app/src/main/java/eu/kanade/domain/manga/interactor/UpdateManga.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt --- .../domain/manga/interactor/UpdateManga.kt | 25 +++++++------ .../settings/screen/SettingsAdvancedScreen.kt | 13 +++++-- .../tachiyomi/data/download/DownloadCache.kt | 35 +++++++++++++++++++ .../data/download/DownloadManager.kt | 32 +++++++++++++++++ .../library/service/LibraryPreferences.kt | 2 ++ .../moko-resources/base/strings.xml | 2 ++ 6 files changed, 96 insertions(+), 13 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 9aa7d7d1f..7117e07af 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 @@ -4,6 +4,7 @@ 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.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 @@ -32,9 +33,8 @@ class UpdateManga( remoteManga: SManga, manualFetch: Boolean, coverCache: CoverCache = Injekt.get(), - // SY --> + libraryPreferences: LibraryPreferences = Injekt.get(), downloadManager: DownloadManager = Injekt.get(), - // SY <-- ): Boolean { val remoteTitle = try { remoteManga.title @@ -42,14 +42,13 @@ class UpdateManga( "" } - // SY --> - val title = if (remoteTitle.isNotBlank() && localManga.ogTitle != remoteTitle) { - downloadManager.renameMangaDir(localManga.ogTitle, remoteTitle, localManga.source) - remoteTitle - } else { - null - } - // SY <-- + // 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 { @@ -69,7 +68,7 @@ class UpdateManga( val thumbnailUrl = remoteManga.thumbnail_url?.takeIf { it.isNotEmpty() } - return mangaRepository.update( + val success = mangaRepository.update( MangaUpdate( id = localManga.id, title = title, @@ -84,6 +83,10 @@ class UpdateManga( initialized = true, ), ) + if (success && title != null) { + downloadManager.renameManga(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 a825b9f1e..be178bf47 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 @@ -88,6 +88,7 @@ import tachiyomi.core.common.util.system.ImageUtil import tachiyomi.core.common.util.system.logcat import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId +import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.GetAllManga import tachiyomi.domain.manga.interactor.ResetViewerFlags import tachiyomi.domain.source.service.SourceManager @@ -114,6 +115,7 @@ object SettingsAdvancedScreen : SearchableSettings { val basePreferences = remember { Injekt.get() } val networkPreferences = remember { Injekt.get() } + val libraryPreferences = remember { Injekt.get() } return listOf( Preference.PreferenceItem.TextPreference( @@ -154,7 +156,7 @@ object SettingsAdvancedScreen : SearchableSettings { getBackgroundActivityGroup(), getDataGroup(), getNetworkGroup(networkPreferences = networkPreferences), - getLibraryGroup(), + getLibraryGroup(libraryPreferences = libraryPreferences), getReaderGroup(basePreferences = basePreferences), getExtensionsGroup(basePreferences = basePreferences), // SY --> @@ -322,7 +324,9 @@ object SettingsAdvancedScreen : SearchableSettings { } @Composable - private fun getLibraryGroup(): Preference.PreferenceGroup { + private fun getLibraryGroup( + libraryPreferences: LibraryPreferences, + ): Preference.PreferenceGroup { val scope = rememberCoroutineScope() val context = LocalContext.current @@ -350,6 +354,11 @@ object SettingsAdvancedScreen : SearchableSettings { } }, ), + Preference.PreferenceItem.SwitchPreference( + preference = 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/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index 5baba5e02..3c45924d6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -307,6 +307,41 @@ class DownloadCache( notifyChanges() } + /** + * Renames a manga in this cache. + * + * @param manga the manga being renamed. + * @param mangaUniFile the manga's new directory. + * @param newTitle the manga's new title. + */ + suspend fun renameManga(manga: Manga, mangaUniFile: UniFile, newTitle: String) { + rootDownloadsDirMutex.withLock { + val sourceDir = rootDownloadsDir.sourceDirs[manga.source] ?: return + val oldMangaDirName = provider.getMangaDirName(/* SY --> */ manga.ogTitle /* SY <-- */) + var oldChapterDirs: MutableSet? = null + // Save the old name's cached chapter dirs + if (sourceDir.mangaDirs.containsKey(oldMangaDirName)) { + oldChapterDirs = sourceDir.mangaDirs[oldMangaDirName]?.chapterDirs + sourceDir.mangaDirs -= oldMangaDirName + } + + // Retrieve/create the cached manga directory for new name + val newMangaDirName = provider.getMangaDirName(newTitle) + var mangaDir = sourceDir.mangaDirs[newMangaDirName] + if (mangaDir == null) { + mangaDir = MangaDirectory(mangaUniFile) + sourceDir.mangaDirs += newMangaDirName to mangaDir + } + + // Add the old chapters to new name's cache + if (!oldChapterDirs.isNullOrEmpty()) { + mangaDir.chapterDirs += oldChapterDirs + } + } + + notifyChanges() + } + suspend fun removeSource(source: Source) { rootDownloadsDirMutex.withLock { rootDownloadsDir.sourceDirs -= source.id 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 f70c2afc1..47a80144a 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -398,6 +398,38 @@ class DownloadManager( } } + /** + * Renames manga download folder + * + * @param manga the manga + * @param newTitle the new manga title. + */ + suspend fun renameManga(manga: Manga, newTitle: String) { + val source = sourceManager.getOrStub(manga.source) + val oldFolder = provider.findMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) ?: return + val newName = provider.getMangaDirName(newTitle) + + if (oldFolder.name == newName) return + + // just to be safe, don't allow downloads for this manga while renaming it + downloader.removeFromQueue(manga) + + 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)) { + cache.renameManga(manga, oldFolder, newTitle) + } else { + logcat(LogPriority.ERROR) { "Failed to rename manga download folder: ${oldFolder.name}" } + } + } + /** * Renames an already downloaded chapter * 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 4cc1fd663..ea5c90b0a 100644 --- a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt @@ -198,6 +198,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 05a24a5af..f7939238a 100755 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -626,6 +626,8 @@ Verbose logging Print verbose logs to system log (reduces app performance) Debug info + Update library manga titles to match source + Warning: if a manga is renamed, it will be removed from the download queue (if present). Website