Add an option to disable the MD5 suffix in chapter names (#3966)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Chopper
2026-10-02 03:31:38 +06:00
committed by GitHub
co-authored by AntsyLich
parent 98ba693054
commit f2464a1ba6
7 changed files with 71 additions and 22 deletions
+1
View File
@@ -17,6 +17,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- Add support for using the user's chosen rating system for Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#3818](https://github.com/mihonapp/mihon/pull/3818))
- Add support for the Year, Month, and Day fields in ComicInfo.xml files for chapter dating ([@MajorTanya](https://github.com/MajorTanya)) ([#3967](https://github.com/mihonapp/mihon/pull/3967))
- Add refresh buttons to trackers in Settings to update displayed usernames (all trackers) & rating systems (where supported) ([@MajorTanya](https://github.com/MajorTanya)) ([#3828](https://github.com/mihonapp/mihon/pull/3828))
- Add setting to toggle chapter name hash suffix ([@choppeh](https://github.com/choppeh)) ([#3966](https://github.com/mihonapp/mihon/pull/3966))
### Improved
- Show updates and upcoming filter icon as active for categories ([@Secozzi](https://github.com/Secozzi)) ([#3772](https://github.com/mihonapp/mihon/pull/3772))
+1 -1
View File
@@ -37,7 +37,7 @@ android {
defaultConfig {
applicationId = "app.mihon"
versionCode = 33
versionCode = 34
versionName = "0.20.4"
buildConfigField("boolean", "TELEMETRY_INCLUDED", "${Config.includeTelemetry}")
@@ -318,6 +318,11 @@ object SettingsAdvancedScreen : SearchableSettings {
title = stringResource(MR.strings.pref_disallow_non_ascii_filenames),
subtitle = stringResource(MR.strings.pref_disallow_non_ascii_filenames_details),
),
Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.enableChapterNameHash,
title = stringResource(MR.strings.pref_enable_chapter_name_hash),
subtitle = stringResource(MR.strings.pref_enable_chapter_name_hash_details),
),
),
)
}
@@ -167,15 +167,25 @@ class DownloadProvider(
chapterScanlator: String?,
chapterUrl: String,
disallowNonAsciiFilenames: Boolean = libraryPreferences.disallowNonAsciiFilenames.get(),
enableChapterNameHash: Boolean = libraryPreferences.enableChapterNameHash.get(),
): String {
var dirName = sanitizeChapterName(chapterName)
if (!chapterScanlator.isNullOrBlank()) {
dirName = chapterScanlator + "_" + dirName
return buildString {
if (!chapterScanlator.isNullOrBlank()) {
append(chapterScanlator + "_")
}
// Subtract 7 bytes for hash and underscore, 4 bytes for .cbz
append(
DiskUtil.buildValidFilename(
sanitizeChapterName(chapterName),
DiskUtil.MAX_FILE_NAME_BYTES - 11,
disallowNonAsciiFilenames,
),
)
if (enableChapterNameHash) {
append("_${md5(chapterUrl).take(6)}")
}
}
// Subtract 7 bytes for hash and underscore, 4 bytes for .cbz
dirName = DiskUtil.buildValidFilename(dirName, DiskUtil.MAX_FILE_NAME_BYTES - 11, disallowNonAsciiFilenames)
dirName += "_" + md5(chapterUrl).take(6)
return dirName
}
/**
@@ -191,7 +201,7 @@ class DownloadProvider(
chapterName: String,
chapterScanlator: String?,
chapterUrl: String,
): List<String> {
): Set<String> {
val sanitizedChapterName = sanitizeChapterName(chapterName)
val chapterNameV1 = DiskUtil.buildValidFilename(
when {
@@ -200,23 +210,27 @@ class DownloadProvider(
},
)
// Get the filename that would be generated if the user were
// using the other value for the disallow non-ASCII
// filenames setting. This ensures that chapters downloaded
// before the user changed the setting can still be found.
val otherChapterDirName =
getChapterDirName(
chapterName,
chapterScanlator,
chapterUrl,
!libraryPreferences.disallowNonAsciiFilenames.get(),
)
// Generate all possible legacy directory name variations by combining
// different states of non-ASCII filenames and chapter name hash settings.
// This ensures that chapters downloaded under any past configuration
// combination can still be successfully found.
val booleanPairPermutation = listOf(false to false, false to true, true to false, true to true)
val othersChapterDirNames = booleanPairPermutation
.map { (disallowNonAsciiFilenames, enableChapterNameHash) ->
getChapterDirName(
chapterName,
chapterScanlator,
chapterUrl,
disallowNonAsciiFilenames,
enableChapterNameHash,
)
}
return buildList(2) {
return buildSet {
// Chapter name without hash (unable to handle duplicate
// chapter names)
add(chapterNameV1)
add(otherChapterDirName)
addAll(othersChapterDirNames)
}
}
@@ -0,0 +1,23 @@
package mihon.core.migration.migrations
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesIntoSet
import dev.zacsweers.metro.Inject
import mihon.core.migration.Migration
import mihon.core.migration.MigrationContext
import tachiyomi.domain.library.service.LibraryPreferences
@Inject
@ContributesIntoSet(AppScope::class)
class ChapterNameSuffixMigration(
private val preference: LibraryPreferences,
) : Migration {
override val version: Float = 34f
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
if (migrationContext.previousVersion in 13..33) {
preference.enableChapterNameHash.set(true)
}
return true
}
}
@@ -219,6 +219,10 @@ class LibraryPreferences(
"disallow_non_ascii_filenames",
false,
)
val enableChapterNameHash: Preference<Boolean> = preferenceStore.getBoolean(
"pref_enable_chapter_name_hash",
false,
)
// endregion
@@ -326,6 +326,8 @@
<string name="pref_hide_missing_chapter_indicators">Hide missing chapter indicators</string>
<string name="pref_disallow_non_ascii_filenames">Disallow non-ASCII filenames</string>
<string name="pref_disallow_non_ascii_filenames_details">Ensures compatibility with certain storage media that don't support Unicode. When this is enabled, you'll need to manually rename source and manga folders by replacing non-ASCII characters with their lowercase UTF-8 hexadecimal representations. Chapter files don't need to be renamed.</string>
<string name="pref_enable_chapter_name_hash">Enable chapter name hash suffix</string>
<string name="pref_enable_chapter_name_hash_details">Ensures a unique hash suffix is added to chapter names to prevent naming conflicts. If disabled, chapters with identical names cannot be downloaded.</string>
<!-- Extension section -->
<string name="multi_lang">Multi</string>