diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/DownloadBookItem.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/DownloadBookItem.kt index 655fcb6fe..af3f2284f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/DownloadBookItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/DownloadBookItem.kt @@ -44,7 +44,6 @@ import androidx.compose.ui.semantics.testTag import com.tonyodev.fetch2.Status import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.core.R.string -import org.kiwix.kiwixmobile.core.downloader.model.toPainter import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar import org.kiwix.kiwixmobile.core.ui.components.ProgressBarStyle import org.kiwix.kiwixmobile.core.ui.models.IconItem @@ -104,7 +103,7 @@ private fun DownloadBookContent( .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { - BookIcon(item.favIcon.toPainter()) + BookIcon(item.favIconUrl, isOnlineLibrary = true) Column( modifier = Modifier .weight(1f) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineBookItem.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineBookItem.kt index d4c113940..10523668c 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineBookItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineBookItem.kt @@ -48,8 +48,6 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.zIndex import org.kiwix.kiwixmobile.R -import org.kiwix.kiwixmobile.core.downloader.model.Base64String -import org.kiwix.kiwixmobile.core.downloader.model.toPainter import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme import org.kiwix.kiwixmobile.core.ui.theme.PureGrey @@ -58,7 +56,7 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONLINE_BOOK_DISABLED_COLOR_ALPHA import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP -import org.kiwix.kiwixmobile.core.zim_manager.KiloByte +import org.kiwix.kiwixmobile.core.zim_manager.Byte import org.kiwix.kiwixmobile.ui.BookDate import org.kiwix.kiwixmobile.ui.BookDescription import org.kiwix.kiwixmobile.ui.BookIcon @@ -167,7 +165,7 @@ private fun OnlineBookContent(item: BookItem, bookUtils: BookUtils) { .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { - BookIcon(Base64String(item.book.favicon).toPainter()) + BookIcon(item.book.favicon, isOnlineLibrary = true) Column( modifier = Modifier .weight(1f) @@ -207,7 +205,7 @@ private fun BookSizeAndDateRow(item: BookItem) { verticalAlignment = Alignment.CenterVertically ) { BookSize( - KiloByte(item.book.size).humanReadable, + Byte(item.book.size).humanReadable, modifier = Modifier.weight(1f).testTag(ONLINE_BOOK_SIZE_TEXT_TESTING_TAG) ) BookDate(item.book.date) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt index c8539a813..df8615ea2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt @@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile.ui import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -31,18 +32,17 @@ import androidx.compose.foundation.layout.width import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.Checkbox -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow +import coil3.compose.AsyncImage import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.downloader.model.Base64String import org.kiwix.kiwixmobile.core.downloader.model.toPainter @@ -53,7 +53,7 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP -import org.kiwix.kiwixmobile.core.zim_manager.KiloByte +import org.kiwix.kiwixmobile.core.zim_manager.Byte import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.ArticleCount import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode @@ -116,7 +116,7 @@ private fun BookContent( if (selectionMode == SelectionMode.MULTI) { BookCheckbox(bookOnDisk, selectionMode, onMultiSelect, onClick, index) } - BookIcon(Base64String(bookOnDisk.book.favicon).toPainter()) + BookIcon(bookOnDisk.book.favicon, isOnlineLibrary = false) BookDetails(Modifier.weight(1f), bookOnDisk) } } @@ -142,14 +142,23 @@ private fun BookCheckbox( } @Composable -fun BookIcon(painter: Painter) { - Icon( - painter = painter, - contentDescription = stringResource(R.string.fav_icon), - modifier = Modifier - .size(BOOK_ICON_SIZE), - tint = Color.Unspecified - ) +fun BookIcon(iconSource: String, isOnlineLibrary: Boolean) { + val modifier = Modifier.size(BOOK_ICON_SIZE) + if (isOnlineLibrary) { + AsyncImage( + model = iconSource, + contentDescription = stringResource(R.string.fav_icon), + modifier = modifier, + placeholder = painterResource(R.drawable.default_zim_file_icon), + error = painterResource(R.drawable.default_zim_file_icon), + ) + } else { + Image( + painter = Base64String(iconSource).toPainter(), + contentDescription = stringResource(R.string.fav_icon), + modifier = modifier + ) + } } @Composable @@ -164,7 +173,7 @@ private fun BookDetails(modifier: Modifier, bookOnDisk: BookOnDisk) { ) { BookDate(bookOnDisk.book.date) Spacer(modifier = Modifier.width(EIGHT_DP)) - BookSize(KiloByte(bookOnDisk.book.size).humanReadable) + BookSize(Byte(bookOnDisk.book.size).humanReadable) Spacer(modifier = Modifier.width(EIGHT_DP)) BookArticleCount( ArticleCount(bookOnDisk.book.articleCount.orEmpty()) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt index ce6df49de..83dcb24a3 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/ZimManageViewModel.kt @@ -446,13 +446,19 @@ class ZimManageViewModel @Inject constructor( ): Flow> = flow { downloadProgress.postValue(context.getString(R.string.starting_downloading_remote_library)) val response = kiwixService.getLibrary() + val resolvedUrl = response.raw().networkResponse?.request?.url + ?: response.raw().request.url + val baseHostUrl = "${resolvedUrl.scheme}://${resolvedUrl.host}" downloadProgress.postValue(context.getString(R.string.parsing_remote_library)) - val isLibraryParsed = onlineLibraryManager.parseOPDSStream(response, KIWIX_OPDS_LIBRARY_URL) - if (isLibraryParsed) { - emit(onlineLibraryManager.getOnlineBooks()) - } else { - emit(emptyList()) - } + val libraryXml = response.body() + val isLibraryParsed = onlineLibraryManager.parseOPDSStream(libraryXml, baseHostUrl) + emit( + if (isLibraryParsed) { + onlineLibraryManager.getOnlineBooks() + } else { + emptyList() + } + ) } .retry(5) .catch { e -> diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/AvailableSpaceCalculator.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/AvailableSpaceCalculator.kt index 7b1193251..73c5fda7a 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/AvailableSpaceCalculator.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/AvailableSpaceCalculator.kt @@ -19,7 +19,6 @@ package org.kiwix.kiwixmobile.zimManager.libraryView import eu.mhutti1.utils.storage.Bytes -import eu.mhutti1.utils.storage.KB import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao @@ -42,7 +41,7 @@ class AvailableSpaceCalculator @Inject constructor( .map { downloads -> downloads.sumOf(DownloadModel::bytesRemaining) } .map { bytesToBeDownloaded -> storageCalculator.availableBytes() - bytesToBeDownloaded } .first() - if (bookItem.book.size.toLong() * KB < trueAvailableBytes) { + if (bookItem.book.size.toLong() < trueAvailableBytes) { successAction.invoke(bookItem) } else { failureAction.invoke(Bytes(trueAvailableBytes).humanReadable) @@ -50,5 +49,5 @@ class AvailableSpaceCalculator @Inject constructor( } suspend fun hasAvailableSpaceForBook(book: LibkiwixBook) = - book.size.toLong() * KB < storageCalculator.availableBytes() + book.size.toLong() < storageCalculator.availableBytes() } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/adapter/LibraryListItem.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/adapter/LibraryListItem.kt index 95b813789..d33ecee0e 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/adapter/LibraryListItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/libraryView/adapter/LibraryListItem.kt @@ -20,7 +20,6 @@ package org.kiwix.kiwixmobile.zimManager.libraryView.adapter import androidx.annotation.StringRes import com.tonyodev.fetch2.Status -import org.kiwix.kiwixmobile.core.downloader.model.Base64String import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel import org.kiwix.kiwixmobile.core.downloader.model.DownloadState import org.kiwix.kiwixmobile.core.downloader.model.Seconds @@ -61,7 +60,7 @@ sealed class LibraryListItem { data class LibraryDownloadItem( val downloadId: Long, - val favIcon: Base64String, + val favIconUrl: String, val title: String, val description: String?, val bytesDownloaded: Long, @@ -76,7 +75,7 @@ sealed class LibraryListItem { constructor(downloadModel: DownloadModel) : this( downloadModel.downloadId, - Base64String(downloadModel.book.favicon), + downloadModel.book.favicon, downloadModel.book.title, downloadModel.book.description, downloadModel.bytesDownloaded, diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt index ce38398e7..09f10679e 100644 --- a/buildSrc/src/main/kotlin/Libs.kt +++ b/buildSrc/src/main/kotlin/Libs.kt @@ -369,4 +369,7 @@ object Libs { const val COMPOSE_LIVE_DATA = "androidx.compose.runtime:runtime-livedata:${Versions.COMPOSE_VERSION}" + + const val COIL3_COMPOSE = "io.coil-kt.coil3:coil-compose:${Versions.COIL_COMPOSE}" + const val COIL3_OKHTTP_COMPOSE = "io.coil-kt.coil3:coil-network-okhttp:${Versions.COIL_COMPOSE}" } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 72dd1badc..d39d9fd84 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -115,6 +115,8 @@ object Versions { const val COMPOSE_MATERIAL3 = "1.3.1" const val TURBINE_FLOW_TEST = "1.2.0" + + const val COIL_COMPOSE = "3.2.0" } /** diff --git a/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt b/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt index dd2df6691..4c1458ea7 100644 --- a/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt +++ b/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt @@ -243,6 +243,8 @@ class AllProjectConfigurer { implementation(Libs.ANDROIDX_ACTIVITY_COMPOSE) implementation(Libs.COMPOSE_TOOLING_PREVIEW) implementation(Libs.COMPOSE_LIVE_DATA) + implementation(Libs.COIL3_COMPOSE) + implementation(Libs.COIL3_OKHTTP_COMPOSE) // Compose UI test implementation androidTestImplementation(Libs.COMPOSE_UI_TEST_JUNIT) diff --git a/core/detekt_baseline.xml b/core/detekt_baseline.xml index 876ea7fd3..93e357e6b 100644 --- a/core/detekt_baseline.xml +++ b/core/detekt_baseline.xml @@ -21,7 +21,7 @@ MagicNumber:DownloaderModule.kt$DownloaderModule$5 MagicNumber:FileUtils.kt$FileUtils$3 MagicNumber:JNIInitialiser.kt$JNIInitialiser$1024 - MagicNumber:KiloByte.kt$KiloByte$1024.0 + MagicNumber:Byte.kt$Byte$1024.0 MagicNumber:MainMenu.kt$MainMenu$99 MagicNumber:OnSwipeTouchListener.kt$OnSwipeTouchListener.GestureListener$100 MagicNumber:SearchResultGenerator.kt$ZimSearchResultGenerator$200 @@ -42,7 +42,7 @@ NestedBlockDepth:StorageDeviceUtils.kt$StorageDeviceUtils$// Amazingly file.canWrite() does not always return the correct value private fun canWrite(file: File): Boolean PackageNaming:ArticleCount.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view PackageNaming:BooksOnDiskListItem.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view - PackageNaming:KiloByte.kt$package org.kiwix.kiwixmobile.core.zim_manager + PackageNaming:Byte.kt$package org.kiwix.kiwixmobile.core.zim_manager PackageNaming:KiwixTag.kt$package org.kiwix.kiwixmobile.core.zim_manager PackageNaming:Language.kt$package org.kiwix.kiwixmobile.core.zim_manager PackageNaming:MountPointProducer.kt$package org.kiwix.kiwixmobile.core.zim_manager diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/DownloadRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/DownloadRoomDao.kt index e1d84a3e9..3186a7663 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/DownloadRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/DownloadRoomDao.kt @@ -18,6 +18,7 @@ package org.kiwix.kiwixmobile.core.dao +import android.util.Base64 import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert @@ -25,16 +26,20 @@ import androidx.room.Query import androidx.room.Update import com.tonyodev.fetch2.Download import com.tonyodev.fetch2.Status.COMPLETED +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.withContext import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.downloader.DownloadRequester import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel import org.kiwix.kiwixmobile.core.downloader.model.DownloadRequest import org.kiwix.kiwixmobile.core.entity.LibkiwixBook +import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem +import org.kiwix.libzim.Archive import javax.inject.Inject @Dao @@ -53,15 +58,37 @@ abstract class DownloadRoomDao { fun allDownloads() = getAllDownloads().map { it.map(::DownloadModel) } - private fun moveCompletedToBooksOnDiskDao(downloadEntities: List) { + @Suppress("InjectDispatcher") + private suspend fun moveCompletedToBooksOnDiskDao(downloadEntities: List) { downloadEntities.filter { it.status == COMPLETED } .takeIf(List::isNotEmpty) - ?.let { - deleteDownloadsList(it) - newBookDao.insert(it.map(BooksOnDiskListItem::BookOnDisk)) + ?.let { completedDownloads -> + deleteDownloadsList(completedDownloads) + // We now use the OPDS stream instead of the custom library.xml handling. + // In the OPDS stream, the favicon is a URL instead of a Base64 string. + // So when a download is completed, we extract the illustration directly from the archive. + val booksOnDisk = completedDownloads.map { download -> + val archive = withContext(Dispatchers.IO) { + Archive(download.file) + } + val favicon = getOnlineBookFaviconForOfflineUsages(archive).orEmpty() + val updatedEntity = download.copy(favIcon = favicon) + BooksOnDiskListItem.BookOnDisk(updatedEntity) + } + newBookDao.insert(booksOnDisk) } } + private fun getOnlineBookFaviconForOfflineUsages(archive: Archive): String? = + if (archive.hasIllustration(ILLUSTRATION_SIZE)) { + Base64.encodeToString( + archive.getIllustrationItem(ILLUSTRATION_SIZE).data.data, + Base64.DEFAULT + ) + } else { + null + } + fun update(download: Download) { getEntityForDownloadId(download.id.toLong())?.let { downloadRoomEntity -> downloadRoomEntity.updateWith(download) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/LibkiwixBookmarks.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/LibkiwixBookmarks.kt index 991c7ee7b..d1e86c9b0 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/LibkiwixBookmarks.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/LibkiwixBookmarks.kt @@ -285,6 +285,7 @@ class LibkiwixBookmarks @Inject constructor( // Check if the book has an illustration of the specified size and encode it to Base64. val favicon = book?.getFavicon() + Log.e(TAG, "getBookmarksList: $favicon") val zimReaderSource = book?.path?.let { ZimReaderSource(File(it)) } // Return the LibkiwixBookmarkItem, filtering out null results. diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/KiwixService.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/KiwixService.kt index 5f549dceb..1ef98b7e6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/KiwixService.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/remote/KiwixService.kt @@ -21,14 +21,16 @@ package org.kiwix.kiwixmobile.core.data.remote import okhttp3.OkHttpClient import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity +import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.scalars.ScalarsConverterFactory +import retrofit2.converter.simplexml.SimpleXmlConverterFactory import retrofit2.http.GET import retrofit2.http.Url interface KiwixService { @GET(OPDS_LIBRARY_NETWORK_PATH) - suspend fun getLibrary(): String? + suspend fun getLibrary(): Response @GET suspend fun getMetaLinks( @@ -43,7 +45,7 @@ interface KiwixService { .baseUrl(baseUrl) .client(okHttpClient) .addConverterFactory(ScalarsConverterFactory.create()) - // .addConverterFactory(SimpleXmlConverterFactory.create()) + .addConverterFactory(SimpleXmlConverterFactory.create()) .build() return retrofit.create(KiwixService::class.java) } @@ -52,6 +54,6 @@ interface KiwixService { companion object { // To fetch the full OPDS catalog. // TODO we will change this to pagination later once we migrate to OPDS properly. - const val OPDS_LIBRARY_NETWORK_PATH = "entries?count=-1" + const val OPDS_LIBRARY_NETWORK_PATH = "v2/entries?count=-1" } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/NetworkModule.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/NetworkModule.kt index 18e6d450a..e0d5a816e 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/NetworkModule.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/NetworkModule.kt @@ -38,7 +38,7 @@ const val CONNECTION_TIMEOUT = 10L const val READ_TIMEOUT = 300L const val CALL_TIMEOUT = 300L const val USER_AGENT = "kiwix-android-version:${BuildConfig.VERSION_CODE}" -const val KIWIX_OPDS_LIBRARY_URL = "https://opds.library.kiwix.org/v2/" +const val KIWIX_OPDS_LIBRARY_URL = "https://opds.library.kiwix.org/" @Module class NetworkModule { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/Base64String.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/Base64String.kt index df06f6980..849cb7f34 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/Base64String.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/Base64String.kt @@ -38,7 +38,7 @@ value class Base64String(private val encodedString: String?) { BitmapFactory.decodeByteArray(it, 0, it.size) } } - } catch (illegalArgumentException: IllegalArgumentException) { + } catch (_: IllegalArgumentException) { null } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt index b0cf08251..7af29cc8b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt @@ -34,7 +34,7 @@ import org.kiwix.kiwixmobile.core.R data class DownloadItem( val downloadId: Long, - val favIcon: Base64String, + val favIconUrl: String, val title: String, val description: String?, val bytesDownloaded: Long, @@ -47,7 +47,7 @@ data class DownloadItem( constructor(downloadModel: DownloadModel) : this( downloadModel.downloadId, - Base64String(downloadModel.book.favicon), + downloadModel.book.favicon, downloadModel.book.title, downloadModel.book.description, downloadModel.bytesDownloaded, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/BookExtensions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/BookExtensions.kt index 7b9b82e09..cbc73a0a1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/BookExtensions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/BookExtensions.kt @@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile.core.extensions import android.util.Base64 +import android.util.Log import org.kiwix.kiwixmobile.core.CoreApp import org.kiwix.kiwixmobile.core.entity.LibkiwixBook import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE @@ -57,6 +58,20 @@ fun LibkiwixBook.buildSearchableText(bookUtils: BookUtils): String = } }.toString() -fun Book.getFavicon(): String? = getIllustration(ILLUSTRATION_SIZE)?.data?.let { - Base64.encodeToString(it, Base64.DEFAULT) -} +fun Book?.getFavicon(): String? = + runCatching { + val illustration = this?.getIllustration(ILLUSTRATION_SIZE) + illustration?.url()?.ifBlank { + illustration.data?.let { + Base64.encodeToString(it, Base64.DEFAULT) + } + } + }.getOrElse { + it.printStackTrace().also { + this?.illustrations?.forEach { illustration -> + Log.e("BOOK", "getFavicon: ${illustration.data} and ${illustration.url()}") + } + Log.e("BOOK", "getFavicon: ${this?.title}") + } + "" + } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ImageViewExtensions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ImageViewExtensions.kt index a046dc6f2..ac38ec97a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ImageViewExtensions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ImageViewExtensions.kt @@ -24,20 +24,6 @@ import androidx.annotation.ColorInt import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat import androidx.core.widget.ImageViewCompat -import org.kiwix.kiwixmobile.core.R -import org.kiwix.kiwixmobile.core.downloader.model.Base64String - -fun ImageView.setBitmap(base64String: Base64String) { - base64String.toBitmap() - ?.let(::setImageBitmap) - ?: kotlin.run { setImageDrawableCompat(R.drawable.default_zim_file_icon) } -} - -// methods that accept inline classes as parameters are not allowed to be called from java -// hence this facade -fun ImageView.setBitmapFromString(string: String?) { - setBitmap(Base64String(string)) -} fun ImageView.setImageDrawableCompat( @DrawableRes id: Int diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt index c19977ec8..a71785914 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt @@ -340,6 +340,7 @@ abstract class CoreReaderFragment : private val navigationHistoryList: MutableList = ArrayList() private var isReadSelection = false private var isReadAloudServiceRunning = false + private var libkiwixBook: Book? = null private var readerLifeCycleScope: CoroutineScope? = null val coreReaderLifeCycleScope: CoroutineScope? @@ -2038,9 +2039,7 @@ abstract class CoreReaderFragment : lifecycleScope.launch { getCurrentWebView()?.url?.let { articleUrl -> zimReaderContainer?.zimFileReader?.let { zimFileReader -> - val libKiwixBook = Book().apply { - update(zimFileReader.jniKiwixReader) - } + val libKiwixBook = getLibkiwixBook(zimFileReader) if (isBookmarked) { repositoryActions?.deleteBookmark(libKiwixBook.id, articleUrl) snackBarRoot?.snack(R.string.bookmark_removed) @@ -2071,6 +2070,19 @@ abstract class CoreReaderFragment : } } + /** + * Returns the libkiwix book evertime when user saves or remove the bookmark. + * the object will be created once to avoid creating it multiple times. + */ + private fun getLibkiwixBook(zimFileReader: ZimFileReader): Book { + libkiwixBook?.let { return it } + val book = Book().apply { + update(zimFileReader.jniKiwixReader) + } + libkiwixBook = book + return book + } + override fun onResume() { super.onResume() updateBottomToolbarVisibility() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/KiloByte.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/Byte.kt similarity index 87% rename from core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/KiloByte.kt rename to core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/Byte.kt index 906a317ff..129e17528 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/KiloByte.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/Byte.kt @@ -23,10 +23,10 @@ import kotlin.math.log10 import kotlin.math.pow @JvmInline -value class KiloByte(private val kilobyteString: String?) { +value class Byte(private val byteString: String?) { val humanReadable - get() = kilobyteString?.toLongOrNull()?.let { - val units = arrayOf("KB", "MB", "GB", "TB") + get() = byteString?.toLongOrNull()?.let { + val units = arrayOf("B", "KB", "MB", "GB", "TB") val conversion = (log10(it.toDouble()) / log10(1024.0)).toInt() DecimalFormat("#,##0.#") .format(it / 1024.0.pow(conversion.toDouble())) +