From 6c5bd3f83e18328acc4d2d8cee11f41f787ac366 Mon Sep 17 00:00:00 2001 From: Osten <11805592+LagradOst@users.noreply.github.com> Date: Sat, 15 Jun 2024 05:07:56 +0200 Subject: [PATCH] fixed reader for external epubs (images + spine) --- .../quicknovel/ReadActivityViewModel.kt | 56 ++++++++++++++++++- .../lagradost/quicknovel/ui/TextAdapter.kt | 18 +++--- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/lagradost/quicknovel/ReadActivityViewModel.kt b/app/src/main/java/com/lagradost/quicknovel/ReadActivityViewModel.kt index f18c7220..d53c4621 100644 --- a/app/src/main/java/com/lagradost/quicknovel/ReadActivityViewModel.kt +++ b/app/src/main/java/com/lagradost/quicknovel/ReadActivityViewModel.kt @@ -2,6 +2,7 @@ package com.lagradost.quicknovel import android.content.Context import android.content.Intent +import android.content.res.Resources import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Rect @@ -12,6 +13,8 @@ import android.text.Spanned import android.widget.Toast import androidx.annotation.WorkerThread import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.toDrawable +import androidx.core.text.getSpans import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -55,6 +58,7 @@ import io.noties.markwon.MarkwonConfiguration import io.noties.markwon.SoftBreakAddsNewLinePlugin import io.noties.markwon.html.HtmlPlugin import io.noties.markwon.image.AsyncDrawable +import io.noties.markwon.image.AsyncDrawableSpan import io.noties.markwon.image.ImageSizeResolver import io.noties.markwon.image.glide.GlideImagesPlugin import kotlinx.coroutines.delay @@ -141,6 +145,21 @@ abstract class AbstractBook { abstract fun getChapterTitle(index: Int): UiText abstract fun getLoadingStatus(index: Int): String? + @Throws + open fun loadImage(image: String): ByteArray? { + return null + } + + fun loadImageBitmap(image: String): Bitmap? { + try { + val data = this.loadImage(image) ?: return null + return BitmapFactory.decodeByteArray(data, 0, data.size) + } catch (t: Throwable) { + logError(t) + return null + } + } + @WorkerThread @Throws abstract suspend fun getChapterData(index: Int, reload: Boolean): String @@ -239,6 +258,7 @@ class QuickBook(val data: QuickStreamData) : AbstractBook() { } class RegularBook(val data: Book) : AbstractBook() { + init { var refs = mutableListOf() data.tableOfContents.tocReferences.forEach { ref -> @@ -252,6 +272,10 @@ class RegularBook(val data: Book) : AbstractBook() { override val canReload = false + override fun loadImage(image: String): ByteArray? { + return data.resources.resourceMap.values.find { x -> x.mediaType.name.contains("image") && image.endsWith(x.href) }?.data + } + override fun size(): Int { return data.tableOfContents.tocReferences.size } @@ -270,7 +294,25 @@ class RegularBook(val data: Book) : AbstractBook() { } override suspend fun getChapterData(index: Int, reload: Boolean): String { - return data.tableOfContents.tocReferences[index].resource.reader.readText() + val start = data.tableOfContents.tocReferences[index].resource + val startIdx = data.spine.getResourceIndex(start) + + val end = data.tableOfContents.tocReferences.getOrNull(index + 1)?.resource + var endIdx = data.spine.getResourceIndex(end) + if (endIdx == -1) { + endIdx = data.spine.size() + } + val builder = StringBuilder() + for (i in startIdx until endIdx) { + val ref = data.spine.spineReferences[i] + // I have no idea, but nonlinear = stop? + if (!ref.isLinear && i != startIdx) { + break + } + builder.append(ref.resource.reader.readText()) + } + + return builder.toString() } override fun expand(last: String): Boolean { @@ -639,7 +681,13 @@ class ReadActivityViewModel : ViewModel() { markwonMutex.withLock { parsed = markwon.parse(rawText) rendered = markwon.render(parsed) - + val asyncDrawables = rendered.getSpans() + for (async in asyncDrawables) { + async.drawable.result = + book.loadImageBitmap(async.drawable.destination)?.toDrawable( + Resources.getSystem() + ) + } //render(rawText, markwon) // this was removed because the reducer did not work /*val split = reducer.reduce(parsed) @@ -734,7 +782,7 @@ class ReadActivityViewModel : ViewModel() { if (loadedChapter >= book.size()) { currentIndex = book.size() - 1 updateIndexAsync(currentIndex, notify = false) - showToast("Resize $loadedChapter -> $currentIndex", Toast.LENGTH_LONG) + showToast("Resize $loadedChapter -> $currentIndex", Toast.LENGTH_LONG) } val char = getKey( @@ -782,6 +830,7 @@ class ReadActivityViewModel : ViewModel() { .usePlugin(GlideImagesPlugin.create(object : GlideImagesPlugin.GlideStore { override fun load(drawable: AsyncDrawable): RequestBuilder { return try { + val newUrl = drawable.destination.substringAfter("&url=") val url = book.resolveUrl( @@ -794,6 +843,7 @@ class ReadActivityViewModel : ViewModel() { Glide.with(context) .load(GlideUrl(url) { mapOf("user-agent" to USER_AGENT) }) + } catch (e: Exception) { logError(e) Glide.with(context) diff --git a/app/src/main/java/com/lagradost/quicknovel/ui/TextAdapter.kt b/app/src/main/java/com/lagradost/quicknovel/ui/TextAdapter.kt index 99429d51..ff8d5ba3 100644 --- a/app/src/main/java/com/lagradost/quicknovel/ui/TextAdapter.kt +++ b/app/src/main/java/com/lagradost/quicknovel/ui/TextAdapter.kt @@ -173,8 +173,8 @@ data class TextConfig( val textSize: Int, val textFont: String, val defaultFont: Typeface, - val backgroundColor : Int, - val bionicReading : Boolean + val backgroundColor: Int, + val bionicReading: Boolean ) { private val fontFile: File? by lazy { if (textFont == "") null else systemFonts.firstOrNull { it.name == textFont } @@ -207,9 +207,11 @@ data class TextConfig( private fun setTextColor(textView: TextView) { textView.setTextColor(textColor) } + private fun setBgTextColor(textView: TextView) { textView.setTextColor(backgroundColor) } + fun setArgs(progressBar: ProgressBar) { progressBar.progressTintList = ColorStateList.valueOf(textColor) progressBar.indeterminateTintList = ColorStateList.valueOf(textColor) @@ -252,7 +254,7 @@ class TextAdapter(private val viewModel: ReadActivityViewModel, var config: Text return true } - fun changeBionicReading(to : Boolean) : Boolean { + fun changeBionicReading(to: Boolean): Boolean { if (config.bionicReading == to) return false config = config.copy(bionicReading = to) return true @@ -291,7 +293,7 @@ class TextAdapter(private val viewModel: ReadActivityViewModel, var config: Text DRAW_FAILED -> SingleFailedBinding.inflate(inflater, parent, false) DRAW_CHAPTER -> SingleFinishedChapterBinding.inflate(inflater, parent, false) DRAW_LOAD -> SingleLoadBinding.inflate(inflater, parent, false) - DRAW_OVERSCROLL -> SingleOverscrollChapterBinding.inflate(inflater,parent,false) + DRAW_OVERSCROLL -> SingleOverscrollChapterBinding.inflate(inflater, parent, false) else -> throw NotImplementedError() } @@ -467,9 +469,11 @@ class TextAdapter(private val viewModel: ReadActivityViewModel, var config: Text is ChapterLoadSpanned -> { DRAW_LOAD } + is ChapterOverscrollSpanned -> { DRAW_OVERSCROLL } + else -> throw NotImplementedError() } } @@ -547,7 +551,7 @@ class TextAdapter(private val viewModel: ReadActivityViewModel, var config: Text } - private fun bindImage(binding : SingleImageBinding, img : AsyncDrawable) { + private fun bindImage(binding: SingleImageBinding, img: AsyncDrawable) { val url = img.destination if (binding.root.url == url) return binding.root.url = url // don't reload if already set @@ -558,13 +562,13 @@ class TextAdapter(private val viewModel: ReadActivityViewModel, var config: Text when (binding) { is SingleImageBinding -> { val img = obj.text.getSpans(0, obj.text.length)[0] - bindImage(binding,img.drawable) + bindImage(binding, img.drawable) binding.root.setOnClickListener { root -> if (root !is TextImageView) { return@setOnClickListener } - showImage(root.context,img.drawable) + showImage(root.context, img.drawable) } /*val size = 300.toPx