🛠️ Improve Chapter parsing
* Made parsing more universal (more books are supported)
This commit is contained in:
parent
e6014866cf
commit
e04bb0aca7
8 changed files with 27 additions and 24 deletions
|
|
@ -3,7 +3,6 @@ package ua.acclorite.book_story
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import ua.acclorite.book_story.data.local.notification.UpdatesNotificationService
|
import ua.acclorite.book_story.data.local.notification.UpdatesNotificationService
|
||||||
|
|
||||||
|
|
@ -23,7 +22,7 @@ class Application : Application() {
|
||||||
)
|
)
|
||||||
|
|
||||||
val notificationManager = getSystemService(
|
val notificationManager = getSystemService(
|
||||||
Context.NOTIFICATION_SERVICE
|
NOTIFICATION_SERVICE
|
||||||
) as NotificationManager
|
) as NotificationManager
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class BookMapperImpl @Inject constructor() : BookMapper {
|
||||||
author = book.author.getAsString(),
|
author = book.author.getAsString(),
|
||||||
textPath = book.textPath,
|
textPath = book.textPath,
|
||||||
description = book.description,
|
description = book.description,
|
||||||
image = if (book.coverImage != null) book.coverImage.toString() else null,
|
image = book.coverImage?.toString(),
|
||||||
category = book.category,
|
category = book.category,
|
||||||
chapters = book.chapters
|
chapters = book.chapters
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,10 @@ import javax.inject.Inject
|
||||||
class DocumentParser @Inject constructor() {
|
class DocumentParser @Inject constructor() {
|
||||||
/**
|
/**
|
||||||
* Parses document to get it's text.
|
* Parses document to get it's text.
|
||||||
* If [fragment] is not null, searches document for specific [fragment].
|
|
||||||
*
|
*
|
||||||
* @return Parsed text line by line.
|
* @return Parsed text line by line.
|
||||||
*/
|
*/
|
||||||
suspend fun Document.parseDocument(fragment: String?): List<String> {
|
suspend fun Document.parseDocument(): List<String> {
|
||||||
val lines = mutableListOf<String>()
|
val lines = mutableListOf<String>()
|
||||||
|
|
||||||
yield()
|
yield()
|
||||||
|
|
@ -32,10 +31,6 @@ class DocumentParser @Inject constructor() {
|
||||||
yield()
|
yield()
|
||||||
|
|
||||||
body()
|
body()
|
||||||
.run {
|
|
||||||
fragment?.let { return@run getElementById(it) ?: this }
|
|
||||||
this
|
|
||||||
}
|
|
||||||
.wholeText()
|
.wholeText()
|
||||||
.lines()
|
.lines()
|
||||||
.forEach { line ->
|
.forEach { line ->
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class EpubTextParser @Inject constructor(
|
||||||
it.readText()
|
it.readText()
|
||||||
}
|
}
|
||||||
|
|
||||||
val chapter = documentParser.run { Jsoup.parse(content).parseDocument(fragment = null) }
|
val chapter = documentParser.run { Jsoup.parse(content).parseDocument() }
|
||||||
if (chapter.isEmpty()) {
|
if (chapter.isEmpty()) {
|
||||||
Log.w(EPUB_TAG, "Chapter ${entry.name} is empty.")
|
Log.w(EPUB_TAG, "Chapter ${entry.name} is empty.")
|
||||||
return@forEach
|
return@forEach
|
||||||
|
|
@ -146,7 +146,7 @@ class EpubTextParser @Inject constructor(
|
||||||
private suspend fun parseWithToc(tocEntry: ZipEntry, zip: ZipFile): List<ChapterWithText>? {
|
private suspend fun parseWithToc(tocEntry: ZipEntry, zip: ZipFile): List<ChapterWithText>? {
|
||||||
Log.i(EPUB_TAG, "TOC Entry: ${tocEntry.name}")
|
Log.i(EPUB_TAG, "TOC Entry: ${tocEntry.name}")
|
||||||
|
|
||||||
val chapters = mutableListOf<ChapterWithText>()
|
val chapters = mutableMapOf<String, ChapterWithText>()
|
||||||
var emptyChapters = 0
|
var emptyChapters = 0
|
||||||
var chapterTextIndex = -1
|
var chapterTextIndex = -1
|
||||||
var chapterIndex = 1
|
var chapterIndex = 1
|
||||||
|
|
@ -172,12 +172,22 @@ class EpubTextParser @Inject constructor(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val uri = Uri.parse(this) ?: return@run this to null
|
Uri.parse(this).path ?: this
|
||||||
(uri.path ?: this) to uri.fragment
|
}
|
||||||
|
|
||||||
|
if (chapters.containsKey(chapterSrc)) {
|
||||||
|
chapters[chapterSrc] = chapters[chapterSrc]!!.run {
|
||||||
|
copy(
|
||||||
|
chapter = chapter.copy(
|
||||||
|
title = "${chapter.title} / $chapterTitle"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
zip.entries().asSequence().find { entry ->
|
zip.entries().asSequence().find { entry ->
|
||||||
entry.name.endsWith(chapterSrc.first)
|
entry.name.endsWith(chapterSrc)
|
||||||
}.apply {
|
}.apply {
|
||||||
if (this == null) {
|
if (this == null) {
|
||||||
Log.e(EPUB_TAG, "No chapter entry found: $chapterTitle")
|
Log.e(EPUB_TAG, "No chapter entry found: $chapterTitle")
|
||||||
|
|
@ -191,9 +201,7 @@ class EpubTextParser @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
val chapter = documentParser.run {
|
val chapter = documentParser.run {
|
||||||
Jsoup.parse(content).parseDocument(
|
Jsoup.parse(content).parseDocument().dropWhile {
|
||||||
fragment = chapterSrc.second
|
|
||||||
).dropWhile {
|
|
||||||
it == chapterTitle // Remove chapter title if present
|
it == chapterTitle // Remove chapter title if present
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +211,9 @@ class EpubTextParser @Inject constructor(
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
chapters.add(
|
chapters.put(
|
||||||
ChapterWithText(
|
key = chapterSrc,
|
||||||
|
value = ChapterWithText(
|
||||||
chapter = Chapter(
|
chapter = Chapter(
|
||||||
index = chapters.size,
|
index = chapters.size,
|
||||||
title = chapterTitle,
|
title = chapterTitle,
|
||||||
|
|
@ -231,6 +240,6 @@ class EpubTextParser @Inject constructor(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapters
|
return chapters.values.toList().sortedBy { it.chapter.index }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ class HtmTextParser @Inject constructor(
|
||||||
Log.i(HTM_TAG, "Started HTM parsing: ${file.name}.")
|
Log.i(HTM_TAG, "Started HTM parsing: ${file.name}.")
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val lines = documentParser.run { Jsoup.parse(file).parseDocument(null) }
|
val lines = documentParser.run { Jsoup.parse(file).parseDocument() }
|
||||||
|
|
||||||
yield()
|
yield()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class HtmlTextParser @Inject constructor(
|
||||||
Log.i(HTML_TAG, "Started HTML parsing: ${file.name}.")
|
Log.i(HTML_TAG, "Started HTML parsing: ${file.name}.")
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val lines = documentParser.run { Jsoup.parse(file).parseDocument(null) }
|
val lines = documentParser.run { Jsoup.parse(file).parseDocument() }
|
||||||
|
|
||||||
yield()
|
yield()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ fun AnimatedTopAppBar(
|
||||||
Box(modifier = Modifier.fillMaxWidth()) {
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
animatedTopBars.forEach { data ->
|
animatedTopBars.forEach { data ->
|
||||||
CustomAnimatedVisibility(
|
CustomAnimatedVisibility(
|
||||||
visible = data.contentVisibility ?: false,
|
visible = data.contentVisibility == true,
|
||||||
enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)),
|
enter = fadeIn(spring(stiffness = Spring.StiffnessMediumLow)),
|
||||||
exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow))
|
exit = fadeOut(spring(stiffness = Spring.StiffnessMediumLow))
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ class Navigator @AssistedInject constructor(
|
||||||
savedStateHandle[USE_BACK_ANIM] = useBackAnimation
|
savedStateHandle[USE_BACK_ANIM] = useBackAnimation
|
||||||
savedStateHandle[CURRENT_SCREEN] = backStack.value.last()
|
savedStateHandle[CURRENT_SCREEN] = backStack.value.last()
|
||||||
|
|
||||||
backStack.value.removeLast()
|
backStack.value.removeAt(backStack.value.lastIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue