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 d5cfc248d..106432aca 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,13 @@ 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 +70,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 +85,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 8e239f075..0d93f318a 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 @@ -64,6 +64,7 @@ import tachiyomi.core.common.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.withUIContext import tachiyomi.core.common.util.system.ImageUtil 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 @@ -86,6 +87,7 @@ object SettingsAdvancedScreen : SearchableSettings { val basePreferences = remember { Injekt.get() } val networkPreferences = remember { Injekt.get() } + val libraryPreferences = remember { Injekt.get() } return listOf( Preference.PreferenceItem.TextPreference( @@ -126,7 +128,7 @@ object SettingsAdvancedScreen : SearchableSettings { getBackgroundActivityGroup(), getDataGroup(), getNetworkGroup(networkPreferences = networkPreferences), - getLibraryGroup(), + getLibraryGroup(libraryPreferences = libraryPreferences), getReaderGroup(basePreferences = basePreferences), getExtensionsGroup(basePreferences = basePreferences), ) @@ -287,7 +289,9 @@ object SettingsAdvancedScreen : SearchableSettings { } @Composable - private fun getLibraryGroup(): Preference.PreferenceGroup { + private fun getLibraryGroup( + libraryPreferences: LibraryPreferences, + ): Preference.PreferenceGroup { val scope = rememberCoroutineScope() val context = LocalContext.current @@ -315,6 +319,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 5fba899ca..9fe50e463 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 6f3cfe0d8..531564adb 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 53665552d..b87b33d3a 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 5a9d86182..e903d5e22 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 05b72f4e5..2fb937ae6 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -616,6 +616,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