Use ComicInfo.xml for chapter metadata in localSource (#2332)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Radon Rosborough
2025-08-06 16:01:54 -07:00
committed by GitHub
parent 49a84c8914
commit 32257e438e
2 changed files with 38 additions and 10 deletions

View File

@@ -11,6 +11,9 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- `Other` - for technical stuff.
## [Unreleased]
### Changed
- LocalSource now reads ComicInfo.xml file for chapter (if available) to display chapter title, number and scanlator ([@raxod502](https://github.com/radian-software)) ([#2332](https://github.com/mihonapp/mihon/pull/2332))
### Fixes
- Fixed scrollbar sometimes not showing during scroll or not reaching the bottom with few items ([@anirudhsnayak](https://github.com/anirudhsnayak)) ([#2304](https://github.com/mihonapp/mihon/pull/2304))

View File

@@ -190,7 +190,7 @@ actual class LocalSource(
noXmlFile == null -> {
val chapterArchives = mangaDirFiles.filter(Archive::isSupported)
val copiedFile = copyComicInfoFileFromArchive(chapterArchives, mangaDir)
val copiedFile = copyComicInfoFileFromChapters(chapterArchives, mangaDir)
if (copiedFile != null) {
setMangaDetailsFromComicInfoFile(copiedFile.openInputStream(), manga)
} else {
@@ -206,13 +206,24 @@ actual class LocalSource(
return@withIOContext manga
}
private fun copyComicInfoFileFromArchive(chapterArchives: List<UniFile>, folder: UniFile): UniFile? {
private fun <T> getComicInfoForChapter(chapter: UniFile, block: (InputStream) -> T): T? {
if (chapter.isDirectory) {
return chapter.findFile(COMIC_INFO_FILE)?.let { file ->
file.openInputStream().use(block)
}
} else {
return chapter.archiveReader(context).use { reader ->
reader.getInputStream(COMIC_INFO_FILE)?.use(block)
}
}
}
private fun copyComicInfoFileFromChapters(chapterArchives: List<UniFile>, folder: UniFile): UniFile? {
for (chapter in chapterArchives) {
chapter.archiveReader(context).use { reader ->
reader.getInputStream(COMIC_INFO_FILE)?.use { stream ->
return copyComicInfoFile(stream, folder)
}
val file = getComicInfoForChapter(chapter) f@{ stream ->
return@f copyComicInfoFile(stream, folder)
}
if (file != null) return file
}
return null
}
@@ -225,12 +236,22 @@ actual class LocalSource(
}
}
private fun setMangaDetailsFromComicInfoFile(stream: InputStream, manga: SManga) {
val comicInfo = AndroidXmlReader(stream, StandardCharsets.UTF_8.name()).use {
private fun parseComicInfo(stream: InputStream): ComicInfo {
return AndroidXmlReader(stream, StandardCharsets.UTF_8.name()).use {
xml.decodeFromReader<ComicInfo>(it)
}
}
manga.copyFromComicInfo(comicInfo)
private fun setMangaDetailsFromComicInfoFile(stream: InputStream, manga: SManga) {
manga.copyFromComicInfo(parseComicInfo(stream))
}
private fun setChapterDetailsFromComicInfoFile(stream: InputStream, chapter: SChapter) {
val comicInfo = parseComicInfo(stream)
comicInfo.title?.let { chapter.name = it.value }
comicInfo.number?.value?.toFloatOrNull()?.let { chapter.chapter_number = it }
comicInfo.translator?.let { chapter.scanlator = it.value }
}
// Chapters
@@ -257,6 +278,10 @@ actual class LocalSource(
format.file.epubReader(context).use { epub ->
epub.fillMetadata(manga, this)
}
} else {
getComicInfoForChapter(chapterFile) { stream ->
setChapterDetailsFromComicInfoFile(stream, this)
}
}
}
}