diff --git a/app/src/main/java/com/aryan/reader/epub/EpubImage.kt b/app/src/main/java/com/aryan/reader/epub/EpubImage.kt index 6e2b83b..2fd2802 100644 --- a/app/src/main/java/com/aryan/reader/epub/EpubImage.kt +++ b/app/src/main/java/com/aryan/reader/epub/EpubImage.kt @@ -27,29 +27,9 @@ import kotlinx.serialization.protobuf.ProtoNumber * Represents an image in an epub book. * * @param absPath The absolute path of the image. - * @param image The image data. */ @OptIn(ExperimentalSerializationApi::class) @Serializable data class EpubImage @OptIn(ExperimentalSerializationApi::class) constructor( - @ProtoNumber(1) val absPath: String, - @ProtoNumber(2) val image: ByteArray -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as EpubImage - - if (absPath != other.absPath) return false - if (!image.contentEquals(other.image)) return false - - return true - } - - override fun hashCode(): Int { - var result = absPath.hashCode() - result = 31 * result + image.contentHashCode() - return result - } -} \ No newline at end of file + @ProtoNumber(1) val absPath: String +) \ No newline at end of file diff --git a/app/src/main/java/com/aryan/reader/epub/EpubParser.kt b/app/src/main/java/com/aryan/reader/epub/EpubParser.kt index c066ce2..dfcee56 100644 --- a/app/src/main/java/com/aryan/reader/epub/EpubParser.kt +++ b/app/src/main/java/com/aryan/reader/epub/EpubParser.kt @@ -577,30 +577,29 @@ class EpubParser(private val context: Context) { private fun parseEpubImages( manifestItems: Map, filesContentMap: Map, - extractionRoot: File // Add this param + @Suppress("UNUSED_PARAMETER") extractionRoot: File ): List { - val imageExtensions = listOf("png", "gif", "jpg", "jpeg", "webp", "svg").map { ".$it" } + val imageExtensions = setOf(".png", ".gif", ".jpg", ".jpeg", ".webp", ".svg") val listedImages = manifestItems.values .filter { it.mediaType.startsWith("image/") } - .mapNotNull { manifestItem -> - val bytes = filesContentMap[manifestItem.absPath]?.data?.takeIf { it.isNotEmpty() } - ?: File(extractionRoot, manifestItem.absPath).takeIf { it.exists() }?.readBytes() - - bytes?.let { EpubImage(absPath = manifestItem.absPath, image = it) } + .map { manifestItem -> + EpubImage(absPath = manifestItem.absPath) } - val unlistedImages = filesContentMap.asSequence() - .filter { (path, _) -> imageExtensions.any { path.endsWith(it, ignoreCase = true) } } - .filterNot { (path, _) -> listedImages.any { it.absPath == path } } - .mapNotNull { (path, file) -> - val bytes = file.data.takeIf { it.isNotEmpty() } - ?: File(extractionRoot, path).takeIf { it.exists() }?.readBytes() + val listedPaths = listedImages.map { it.absPath }.toSet() - bytes?.let { EpubImage(absPath = path, image = it) } + val unlistedImages = filesContentMap.keys + .filter { path -> + val lowerPath = path.lowercase() + imageExtensions.any { lowerPath.endsWith(it) } && !listedPaths.contains(path) + } + .map { path -> + EpubImage(absPath = path) } - return (listedImages + unlistedImages).distinctBy { it.absPath }.toList() + Timber.d("Identified ${listedImages.size + unlistedImages.size} images (content not loaded into memory).") + return (listedImages + unlistedImages).distinctBy { it.absPath } } private fun parseCoverImage( diff --git a/app/src/main/java/com/aryan/reader/epub/MobiParser.kt b/app/src/main/java/com/aryan/reader/epub/MobiParser.kt index 7bb7b52..ef83903 100644 --- a/app/src/main/java/com/aryan/reader/epub/MobiParser.kt +++ b/app/src/main/java/com/aryan/reader/epub/MobiParser.kt @@ -109,8 +109,6 @@ class MobiParser(private val context: Context) { private external fun parseMobiFile(filePath: String): ParsedMobiData? companion object { - private const val TAG = "MobiParser" - private const val AZW3_TAG = "AZW3_DEBUG" const val EXTRACTED_EPUB_DIR_NAME = "extracted_epubs" init { @@ -135,7 +133,7 @@ class MobiParser(private val context: Context) { } Timber.d("MOBI stream saved to temporary file: ${tempFile.absolutePath}") } catch (e: Exception) { - Timber.e("Failed to write InputStream to temporary file.", e) + Timber.e(e, "Failed to write InputStream to temporary file.") tempFile.delete() return@withContext null } @@ -143,7 +141,7 @@ class MobiParser(private val context: Context) { val parsedData = try { parseMobiFile(tempFile.absolutePath) } catch (e: UnsatisfiedLinkError) { - Timber.e("JNI call failed. Is the native library loaded correctly?", e) + Timber.e(e, "JNI call failed. Is the native library loaded correctly?") null } finally { tempFile.delete() @@ -177,7 +175,7 @@ class MobiParser(private val context: Context) { file.writeBytes(resource.data) Timber.d("Wrote resource to disk -> Path: ${file.absolutePath}, Type: ${resource.mediaType}, Size: ${resource.data.size}") } catch (e: Exception) { - Timber.e("Parser: FAILED to write resource to disk: ${resource.path}", e) + Timber.e(e, "Parser: FAILED to write resource to disk: ${resource.path}") } } @@ -229,7 +227,7 @@ class MobiParser(private val context: Context) { val chapterHtmlParts = mutableListOf>() val sortedToc = parsedData.toc?.sorted() - if (sortedToc != null && sortedToc.isNotEmpty()) { + if (!sortedToc.isNullOrEmpty()) { Timber.d("Splitting content using TOC (${sortedToc.size} entries).") for (i in sortedToc.indices) { val tocEntry = sortedToc[i] @@ -268,14 +266,14 @@ class MobiParser(private val context: Context) { plainTextContent = doc.text() ) } catch (e: Exception) { - Timber.e("Failed to process split chapter $index", e) + Timber.e(e, "Failed to process split chapter $index") null } } val images = parsedData.resources .filter { it.mediaType.startsWith("image/") } - .map { EpubImage(absPath = it.path, image = it.data) } + .map { EpubImage(absPath = it.path) } val cssContent = parsedData.resources .filter { it.mediaType == "text/css" } diff --git a/app/src/main/java/com/aryan/reader/tts/TtsController.kt b/app/src/main/java/com/aryan/reader/tts/TtsController.kt index cbfc425..77e31ce 100644 --- a/app/src/main/java/com/aryan/reader/tts/TtsController.kt +++ b/app/src/main/java/com/aryan/reader/tts/TtsController.kt @@ -236,7 +236,7 @@ class TtsController(context: Context) : Player.Listener { isPlaying = controller.isPlaying, isLoading = isLoading, currentText = if (isPlaybackActive) { - currentTextFromMediaItem ?: customState.getString("currentText") + currentTextFromMediaItem } else { if (isLoading) currentState.currentText else null }, diff --git a/app/src/main/java/com/aryan/reader/tts/TtsPlaybackManager.kt b/app/src/main/java/com/aryan/reader/tts/TtsPlaybackManager.kt index a65daea..f9439ea 100644 --- a/app/src/main/java/com/aryan/reader/tts/TtsPlaybackManager.kt +++ b/app/src/main/java/com/aryan/reader/tts/TtsPlaybackManager.kt @@ -615,7 +615,6 @@ class TtsPlaybackManager( private fun createStateButton(state: TtsState): CommandButton { val bundle = Bundle().apply { putBoolean("isLoading", state.isLoading) - putString("currentText", state.currentText) putString("errorMessage", state.errorMessage) putString("speakerId", state.speakerId) putBoolean("sessionEndedByStop", state.sessionEndedByStop)