From 571d940894592a5ac7935abe53adf98328144d30 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 11:44:12 +0530 Subject: [PATCH 01/19] Created ZimReaderSource for creating the zimFileReader object at one place --- .../core/reader/ZimReaderSource.kt | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt new file mode 100644 index 0000000000..ce33db3e02 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt @@ -0,0 +1,130 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.reader + +import android.content.res.AssetFileDescriptor +import android.net.Uri +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.FileProvider +import androidx.core.net.toUri +import org.kiwix.kiwixmobile.core.CoreApp +import org.kiwix.kiwixmobile.core.extensions.canReadFile +import org.kiwix.kiwixmobile.core.extensions.isFileExist +import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getAssetFileDescriptorFromUri +import org.kiwix.kiwixmobile.core.utils.files.FileUtils.isFileDescriptorCanOpenWithLibkiwix +import org.kiwix.libzim.Archive +import org.kiwix.libzim.FdInput +import java.io.File + +class ZimReaderSource( + val file: File? = null, + val uri: Uri? = null, + private val assetFileDescriptorList: List? = null +) { + constructor(uri: Uri) : this( + uri = uri, + assetFileDescriptorList = getAssetFileDescriptorFromUri(CoreApp.instance, uri) + ) + + constructor(file: File) : this(file = file, uri = null) + + companion object { + fun fromDatabaseValue(databaseValue: String?) = + databaseValue?.run { + if (startsWith("content://")) ZimReaderSource(toUri()) + else ZimReaderSource(File(this)) + } + } + + fun exists(): Boolean { + return when { + file != null -> file.isFileExist() + assetFileDescriptorList?.isNotEmpty() == true -> + assetFileDescriptorList[0].parcelFileDescriptor.fileDescriptor.valid() + + else -> false + } + } + + fun canOpenInLibkiwix(): Boolean { + return when { + file?.canReadFile() == true -> true + assetFileDescriptorList?.get(0)?.parcelFileDescriptor?.fd + ?.let(::isFileDescriptorCanOpenWithLibkiwix) == true -> true + + else -> false + } + } + + fun createArchive(): Archive? { + if (canOpenInLibkiwix()) { + return file?.let { + Archive(it.canonicalPath) + } ?: assetFileDescriptorList?.let { + val fdInputArray = getFdInputArrayFromAssetFileDescriptorList(assetFileDescriptorList) + return@let if (fdInputArray.size == 1) { + Archive(fdInputArray[0]) + } else { + Archive(fdInputArray) + } + } + } + + return null + } + + private fun getFdInputArrayFromAssetFileDescriptorList( + assetFileDescriptorList: List + ): Array = + assetFileDescriptorList.map { + FdInput( + it.parcelFileDescriptor.fileDescriptor, + it.startOffset, + it.length + ) + }.toTypedArray() + + fun toDatabase(): String = file?.canonicalPath ?: uri.toString() + + override fun equals(other: Any?): Boolean { + return when { + file != null && other is ZimReaderSource && other.file != null -> + file.canonicalPath == other.file.canonicalPath + + uri != null && other is ZimReaderSource && other.uri != null -> uri == other.uri + else -> false + } + } + + fun getUri(activity: AppCompatActivity): Uri? { + return when { + file != null -> { + FileProvider.getUriForFile( + activity, + "${activity.packageName}.fileprovider", + file + ) + } + + else -> uri + } + } + + override fun hashCode(): Int = file?.hashCode() ?: assetFileDescriptorList.hashCode() +} From 8fffb1018e0ee4c91d1f32c48d8e2932918bb275 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 12:03:17 +0530 Subject: [PATCH 02/19] Refctored the ZimFileReader and ZimReaderContainer to use ZimReaderSource instead of directly using the file and fileDescriptor --- .../kiwixmobile/core/reader/ZimFileReader.kt | 76 +++++-------------- .../core/reader/ZimReaderContainer.kt | 31 ++------ .../core/reader/ZimReaderSource.kt | 19 +++-- 3 files changed, 35 insertions(+), 91 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt index 810080700b..7329cf1e35 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimFileReader.kt @@ -39,7 +39,6 @@ import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.libkiwix.JNIKiwixException import org.kiwix.libzim.Archive import org.kiwix.libzim.DirectAccessInfo -import org.kiwix.libzim.FdInput import org.kiwix.libzim.Item import org.kiwix.libzim.SuggestionSearch import org.kiwix.libzim.SuggestionSearcher @@ -58,33 +57,35 @@ private const val TAG = "ZimFileReader" @Suppress("LongParameterList") class ZimFileReader constructor( - val zimFile: File?, - val assetFileDescriptorList: List = emptyList(), - val assetDescriptorFilePath: String? = null, + val zimReaderSource: ZimReaderSource, val jniKiwixReader: Archive, private val darkModeConfig: DarkModeConfig, private val searcher: SuggestionSearcher ) { interface Factory { - suspend fun create(file: File): ZimFileReader? - suspend fun create( - assetFileDescriptorList: List, - filePath: String? = null - ): ZimFileReader? + suspend fun create(zimReaderSource: ZimReaderSource): ZimFileReader? class Impl @Inject constructor(private val darkModeConfig: DarkModeConfig) : Factory { - override suspend fun create(file: File): ZimFileReader? = + override suspend fun create(zimReaderSource: ZimReaderSource): ZimFileReader? = withContext(Dispatchers.IO) { // Bug Fix #3805 try { - val archive = Archive(file.canonicalPath) - ZimFileReader( - file, - darkModeConfig = darkModeConfig, - jniKiwixReader = archive, - searcher = SuggestionSearcher(archive) - ).also { - Log.e(TAG, "create: ${file.path}") + zimReaderSource.createArchive()?.let { + ZimFileReader( + zimReaderSource, + darkModeConfig = darkModeConfig, + jniKiwixReader = it, + searcher = SuggestionSearcher(it) + ).also { + Log.e(TAG, "create: ${zimReaderSource.toDatabase()}") + } + } ?: kotlin.run { + Log.e( + TAG, + "Error in creating ZimFileReader," + + " because file does not exist on path: ${zimReaderSource.toDatabase()}" + ) + null } } catch (ignore: JNIKiwixException) { null @@ -92,45 +93,6 @@ class ZimFileReader constructor( null } } - - override suspend fun create( - assetFileDescriptorList: List, - filePath: String? - ): ZimFileReader? = withContext(Dispatchers.IO) { // Bug Fix #3805 - try { - val fdInputArray = getFdInputArrayFromAssetFileDescriptorList(assetFileDescriptorList) - val archive = if (fdInputArray.size == 1) { - Archive(fdInputArray[0]) - } else { - Archive(fdInputArray) - } - ZimFileReader( - null, - assetFileDescriptorList, - assetDescriptorFilePath = filePath, - darkModeConfig = darkModeConfig, - jniKiwixReader = archive, - searcher = SuggestionSearcher(archive) - ).also { - Log.e(TAG, "create: with fileDescriptor") - } - } catch (ignore: JNIKiwixException) { - null - } catch (ignore: Exception) { // for handing the error, if any zim file is corrupted - null - } - } - - private fun getFdInputArrayFromAssetFileDescriptorList( - assetFileDescriptorList: List - ): Array = - assetFileDescriptorList.map { - FdInput( - it.parcelFileDescriptor.fileDescriptor, - it.startOffset, - it.length - ) - }.toTypedArray() } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt index 46027b840f..c0bdefc03b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderContainer.kt @@ -17,12 +17,9 @@ */ package org.kiwix.kiwixmobile.core.reader -import android.content.res.AssetFileDescriptor import android.webkit.WebResourceResponse import kotlinx.coroutines.runBlocking -import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Factory -import java.io.File import java.net.HttpURLConnection import javax.inject.Inject import javax.inject.Singleton @@ -35,25 +32,13 @@ class ZimReaderContainer @Inject constructor(private val zimFileReaderFactory: F field = value } - fun setZimFile(file: File?) { - if (file?.canonicalPath == zimFileReader?.zimFile?.canonicalPath) { + fun setZimReaderSource(zimReaderSource: ZimReaderSource?) { + if (zimReaderSource == zimFileReader?.zimReaderSource) { return } zimFileReader = runBlocking { - if (file?.isFileExist() == true) zimFileReaderFactory.create(file) - else null - } - } - - fun setZimFileDescriptor( - assetFileDescriptorList: List, - filePath: String? = null - ) { - zimFileReader = runBlocking { - if (assetFileDescriptorList.isNotEmpty() && - assetFileDescriptorList[0].parcelFileDescriptor.fileDescriptor.valid() - ) - zimFileReaderFactory.create(assetFileDescriptorList, filePath) + if (zimReaderSource?.exists() == true && zimReaderSource.canOpenInLibkiwix()) + zimFileReaderFactory.create(zimReaderSource) else null } } @@ -87,13 +72,7 @@ class ZimReaderContainer @Inject constructor(private val zimFileReaderFactory: F } } - val zimFile get() = zimFileReader?.zimFile - - /** - * Return the zimFile path if opened from file else return the filePath of assetFileDescriptor - */ - val zimCanonicalPath - get() = zimFileReader?.zimFile?.canonicalPath ?: zimFileReader?.assetDescriptorFilePath + val zimReaderSource get() = zimFileReader?.zimReaderSource val zimFileTitle get() = zimFileReader?.title val mainPage get() = zimFileReader?.mainPage val id get() = zimFileReader?.id diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt index ce33db3e02..f9e7cd25a8 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt @@ -74,15 +74,18 @@ class ZimReaderSource( fun createArchive(): Archive? { if (canOpenInLibkiwix()) { - return file?.let { - Archive(it.canonicalPath) - } ?: assetFileDescriptorList?.let { - val fdInputArray = getFdInputArrayFromAssetFileDescriptorList(assetFileDescriptorList) - return@let if (fdInputArray.size == 1) { - Archive(fdInputArray[0]) - } else { - Archive(fdInputArray) + return when { + file != null -> Archive(file.canonicalPath) + assetFileDescriptorList?.isNotEmpty() == true -> { + val fdInputArray = getFdInputArrayFromAssetFileDescriptorList(assetFileDescriptorList) + if (fdInputArray.size == 1) { + Archive(fdInputArray[0]) + } else { + Archive(fdInputArray) + } } + + else -> null } } From da51cfc02dc819b72cb18ddcb94c5b16ab42c7cb Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 14:22:24 +0530 Subject: [PATCH 03/19] Refactored the entities, and dao to use the ZimReaderSource instead of zimFilePath. Also, Refactored the bookmark saving functionality with this change --- .../page/bookmarks/LibkiwixBookmarkTest.kt | 2 +- .../kiwix/kiwixmobile/core/dao/HistoryDao.kt | 13 ++++- .../kiwixmobile/core/dao/HistoryRoomDao.kt | 11 +++- .../kiwixmobile/core/dao/LibkiwixBookmarks.kt | 53 +++++++++++-------- .../kiwix/kiwixmobile/core/dao/NewBookDao.kt | 13 ++--- .../kiwixmobile/core/dao/NewBookmarksDao.kt | 13 ++++- .../kiwix/kiwixmobile/core/dao/NewNoteDao.kt | 13 ++++- .../kiwixmobile/core/dao/NotesRoomDao.kt | 14 ++++- .../core/dao/entities/BookOnDiskEntity.kt | 16 +++--- .../core/dao/entities/BookmarkEntity.kt | 9 +++- .../core/dao/entities/HistoryEntity.kt | 9 +++- .../core/dao/entities/HistoryRoomEntity.kt | 9 +++- .../core/dao/entities/NotesEntity.kt | 9 +++- .../core/dao/entities/NotesRoomEntity.kt | 9 +++- .../kiwixmobile/core/page/adapter/Page.kt | 4 +- .../page/bookmark/adapter/BookmarkItem.kt | 7 +-- .../bookmark/adapter/LibkiwixBookmarkItem.kt | 15 ++++-- .../page/history/adapter/HistoryListItem.kt | 11 ++-- .../core/page/notes/adapter/NoteListItem.kt | 9 ++-- .../adapter/BooksOnDiskListItem.kt | 11 ++-- .../kiwixmobile/core/page/PageTestHelpers.kt | 2 +- 21 files changed, 177 insertions(+), 75 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt index 4edcc652a2..f86a28b931 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/page/bookmarks/LibkiwixBookmarkTest.kt @@ -166,7 +166,7 @@ class LibkiwixBookmarkTest : BaseActivityTest() { LibkiwixBookmarkItem( bookmark, coreReaderFragment.zimReaderContainer?.zimFileReader?.favicon, - coreReaderFragment.zimReaderContainer?.zimFileReader?.zimFile?.canonicalPath + coreReaderFragment.zimReaderContainer?.zimFileReader?.zimReaderSource ) coreReaderFragment.libkiwixBookmarks?.saveBookmark(libkiwixItem).also { bookmarkList.add(libkiwixItem) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryDao.kt index 0bab34a828..1ea20dc67c 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryDao.kt @@ -25,6 +25,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.HistoryEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import javax.inject.Inject class HistoryDao @Inject constructor(val box: Box) : PageDao { @@ -33,7 +34,17 @@ class HistoryDao @Inject constructor(val box: Box) : PageDao { box.query { orderDesc(HistoryEntity_.timeStamp) } - ).map { it.map(::HistoryItem) } + ).map { + it.map { historyEntity -> + historyEntity.zimFilePath?.let { filePath -> + // set zimReaderSource for previously saved history items + fromDatabaseValue(filePath)?.let { zimReaderSource -> + historyEntity.zimReaderSource = zimReaderSource + } + } + HistoryItem(historyEntity) + } + } override fun pages(): Flowable> = history() override fun deletePages(pagesToDelete: List) = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt index 0741841169..79ab8bebbd 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt @@ -28,6 +28,7 @@ import io.reactivex.Flowable import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Dao abstract class HistoryRoomDao : PageDao { @@ -35,7 +36,15 @@ abstract class HistoryRoomDao : PageDao { abstract fun historyRoomEntity(): Flowable> fun history(): Flowable> = historyRoomEntity().map { - it.map(HistoryListItem::HistoryItem) + it.map { historyEntity -> + historyEntity.zimFilePath?.let { filePath -> + // set zimReaderSource for previously saved history items + ZimReaderSource.fromDatabaseValue(filePath)?.let { zimReaderSource -> + historyEntity.zimReaderSource = zimReaderSource + } + } + HistoryListItem.HistoryItem(historyEntity) + } } override fun pages() = history() 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 e53f6f29b8..2659eef219 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 @@ -36,10 +36,12 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.libkiwix.Book @@ -270,11 +272,12 @@ class LibkiwixBookmarks @Inject constructor( Base64.encodeToString(it, Base64.DEFAULT) } + val zimReaderSource = book?.path?.let { ZimReaderSource(File(it)) } // Return the LibkiwixBookmarkItem, filtering out null results. return@mapNotNull LibkiwixBookmarkItem( bookmark, favicon, - book?.path + zimReaderSource ).also { // set the bookmark change to false to avoid reloading the data from libkiwix bookmarksChanged = false @@ -289,7 +292,7 @@ class LibkiwixBookmarks @Inject constructor( @Suppress("NestedBlockDepth") private fun deleteDuplicateBookmarks() { - bookmarkList.groupBy { it.bookmarkUrl to it.zimFilePath } + bookmarkList.groupBy { it.bookmarkUrl to it.zimReaderSource } .filter { it.value.size > 1 } .forEach { (_, value) -> value.drop(1).forEach { bookmarkItem -> @@ -297,30 +300,13 @@ class LibkiwixBookmarks @Inject constructor( } } // Fixes #3890 - bookmarkList.groupBy { it.title to it.zimFilePath } + bookmarkList.groupBy { it.title to it.zimReaderSource } .filter { it.value.size > 1 } .forEach { (_, value) -> value.forEach { bookmarkItem -> // This is a special case where two urls have the same title in a zim file. val coreApp = sharedPreferenceUtil.context as CoreApp - val zimFileReader = if (coreApp.getMainActivity().isCustomApp()) { - // in custom apps we are using the assetFileDescriptor so we do not have the filePath - // and in custom apps there is only a single zim file so we are directly - // getting the zimFileReader object. - zimReaderContainer?.zimFileReader - } else { - bookmarkItem.zimFilePath?.let { - val archive = Archive(it) - ZimFileReader( - File(it), - emptyList(), - null, - archive, - DarkModeConfig(sharedPreferenceUtil, sharedPreferenceUtil.context), - SuggestionSearcher(archive) - ) - } - } + val zimFileReader = getZimFileReaderFromBookmark(bookmarkItem, coreApp) // get the redirect entry so that we can delete the other bookmark. zimFileReader?.getPageUrlFrom(bookmarkItem.title)?.let { // check if the bookmark url is not equals to redirect entry, @@ -334,11 +320,34 @@ class LibkiwixBookmarks @Inject constructor( } } + private fun getZimFileReaderFromBookmark( + bookmarkItem: LibkiwixBookmarkItem, + coreApp: CoreApp + ): ZimFileReader? { + return if (coreApp.getMainActivity().isCustomApp()) { + // in custom apps we are using the assetFileDescriptor so we do not have the filePath + // and in custom apps there is only a single zim file so we are directly + // getting the zimFileReader object. + zimReaderContainer?.zimFileReader + } else { + bookmarkItem.zimReaderSource?.let { + it.createArchive()?.let { archive -> + ZimFileReader( + it, + archive, + DarkModeConfig(sharedPreferenceUtil, sharedPreferenceUtil.context), + SuggestionSearcher(archive) + ) + } + } + } + } + private fun isBookMarkExist(libkiwixBookmarkItem: LibkiwixBookmarkItem): Boolean = getBookmarksList() .any { it.url == libkiwixBookmarkItem.bookmarkUrl && - it.zimFilePath == libkiwixBookmarkItem.zimFilePath + it.zimReaderSource == libkiwixBookmarkItem.zimReaderSource } private fun flowableBookmarkList( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index b01e22ee30..721a58b389 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -24,6 +24,7 @@ import io.objectbox.query.QueryBuilder import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_ import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import javax.inject.Inject @@ -31,7 +32,7 @@ class NewBookDao @Inject constructor(private val box: Box) { fun books() = box.asFlowable() .doOnNext(::removeBooksThatDoNotExist) - .map { books -> books.filter { it.file.exists() } } + .map { books -> books.filter { it.zimReaderSource.exists() } } .map { it.map(::BookOnDisk) } fun getBooks() = box.all.map(::BookOnDisk) @@ -47,14 +48,14 @@ class NewBookDao @Inject constructor(private val box: Box) { private fun uniqueBooksByFile(booksOnDisk: List): List { val booksWithSameFilePath = booksWithSameFilePath(booksOnDisk) return booksOnDisk.filter { bookOnDisk: BookOnDisk -> - booksWithSameFilePath.find { it.file.path == bookOnDisk.file.path } == null + booksWithSameFilePath.find { it.zimReaderSource == bookOnDisk.zimReaderSource } == null } } private fun booksWithSameFilePath(booksOnDisk: List) = box.query { inValues( - BookOnDiskEntity_.file, booksOnDisk.map { it.file.path }.toTypedArray(), + BookOnDiskEntity_.file, booksOnDisk.map { it.zimReaderSource.toDatabase() }.toTypedArray(), QueryBuilder.StringOrder.CASE_INSENSITIVE ) }.find() @@ -77,11 +78,11 @@ class NewBookDao @Inject constructor(private val box: Box) { @Suppress("UnsafeCallOnNullableType") fun migrationInsert(books: List) { - insert(books.map { BookOnDisk(book = it, file = it.file!!) }) + insert(books.map { BookOnDisk(book = it, zimReaderSource = ZimReaderSource(it.file!!)) }) } private fun removeBooksThatDoNotExist(books: MutableList) { - delete(books.filterNot { it.file.exists() }) + delete(books.filterNot { it.zimReaderSource.exists() }) } private fun delete(books: List) { @@ -90,7 +91,7 @@ class NewBookDao @Inject constructor(private val box: Box) { fun bookMatching(downloadTitle: String) = box.query { endsWith( - BookOnDiskEntity_.file, downloadTitle, + BookOnDiskEntity_.zimReaderSource, downloadTitle, QueryBuilder.StringOrder.CASE_INSENSITIVE ) }.findFirst() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDao.kt index 03b2a890f8..36629f0e72 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDao.kt @@ -27,6 +27,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import javax.inject.Inject class NewBookmarksDao @Inject constructor(val box: Box) : PageDao { @@ -34,7 +35,17 @@ class NewBookmarksDao @Inject constructor(val box: Box) : PageDa box.query { order(BookmarkEntity_.bookmarkTitle) } - ).map { it.map(::BookmarkItem) } + ).map { + it.map { bookmarkEntity -> + bookmarkEntity.zimFilePath?.let { filePath -> + // set zimReaderSource for previously saved bookmarks + fromDatabaseValue(filePath)?.let { zimReaderSource -> + bookmarkEntity.zimReaderSource = zimReaderSource + } + } + BookmarkItem(bookmarkEntity) + } + } override fun pages(): Flowable> = bookmarks() override fun deletePages(pagesToDelete: List) = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewNoteDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewNoteDao.kt index 9e7483460c..68a4ebf078 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewNoteDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewNoteDao.kt @@ -26,6 +26,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import javax.inject.Inject class NewNoteDao @Inject constructor(val box: Box) : PageDao { @@ -33,7 +34,17 @@ class NewNoteDao @Inject constructor(val box: Box) : PageDao { box.query { order(NotesEntity_.noteTitle) } - ).map { it.map(::NoteListItem) } + ).map { + it.map { notesEntity -> + notesEntity.zimFilePath?.let { filePath -> + // set zimReaderSource for previously saved notes + fromDatabaseValue(filePath)?.let { zimReaderSource -> + notesEntity.zimReaderSource = zimReaderSource + } + } + NoteListItem(notesEntity) + } + } override fun pages(): Flowable> = notes() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt index 461de6173d..f772d242b2 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NotesRoomDao.kt @@ -26,13 +26,25 @@ import io.reactivex.Flowable import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue @Dao abstract class NotesRoomDao : PageDao { @Query("SELECT * FROM NotesRoomEntity ORDER BY NotesRoomEntity.noteTitle") abstract fun notesAsEntity(): Flowable> - fun notes(): Flowable> = notesAsEntity().map { it.map(::NoteListItem) } + fun notes(): Flowable> = notesAsEntity().map { + it.map { notesEntity -> + notesEntity.zimFilePath?.let { filePath -> + // set zimReaderSource for previously saved notes + fromDatabaseValue(filePath)?.let { zimReaderSource -> + notesEntity.zimReaderSource = zimReaderSource + } + } + NoteListItem(notesEntity) + } + } + override fun pages(): Flowable> = notes() override fun deletePages(pagesToDelete: List) = deleteNotes(pagesToDelete as List) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt index 8c85cc9309..c8fa41f555 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt @@ -23,14 +23,16 @@ import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import io.objectbox.converter.PropertyConverter import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import java.io.File @Entity data class BookOnDiskEntity( @Id var id: Long = 0, - @Convert(converter = StringToFileConverter::class, dbType = String::class) - val file: File = File(""), + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + val zimReaderSource: ZimReaderSource, val bookId: String, val title: String, val description: String?, @@ -48,7 +50,7 @@ data class BookOnDiskEntity( ) { constructor(bookOnDisk: BookOnDisk) : this( 0, - bookOnDisk.file, + bookOnDisk.zimReaderSource, bookOnDisk.book.id, bookOnDisk.book.title, bookOnDisk.book.description, @@ -83,8 +85,10 @@ data class BookOnDiskEntity( } } -class StringToFileConverter : PropertyConverter { - override fun convertToDatabaseValue(entityProperty: File?) = entityProperty?.path ?: "" +class ZimSourceConverter : PropertyConverter { + override fun convertToDatabaseValue(entityProperty: ZimReaderSource?) = + entityProperty?.toDatabase() ?: "" - override fun convertToEntityProperty(databaseValue: String?) = File(databaseValue ?: "") + override fun convertToEntityProperty(databaseValue: String?): ZimReaderSource = + fromDatabaseValue(databaseValue) ?: ZimReaderSource(File("")) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookmarkEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookmarkEntity.kt index 9d29d0735a..0f3c28d601 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookmarkEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookmarkEntity.kt @@ -17,16 +17,20 @@ */ package org.kiwix.kiwixmobile.core.dao.entities +import io.objectbox.annotation.Convert import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Entity data class BookmarkEntity( @Id var id: Long = 0, val zimId: String, var zimName: String, - var zimFilePath: String?, + var zimFilePath: String?, // keep this to handle previously saved bookmarks + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + var zimReaderSource: ZimReaderSource?, var bookmarkUrl: String, var bookmarkTitle: String, var favicon: String? @@ -35,7 +39,8 @@ data class BookmarkEntity( item.databaseId, item.zimId, item.zimName, - item.zimFilePath, + null, // pass null for new bookmarks + item.zimReaderSource, item.bookmarkUrl, item.title, item.favicon diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt index d1012dae03..3ae3e95271 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt @@ -17,16 +17,20 @@ */ package org.kiwix.kiwixmobile.core.dao.entities +import io.objectbox.annotation.Convert import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Entity data class HistoryEntity( @Id var id: Long = 0L, val zimId: String, val zimName: String, - val zimFilePath: String, + val zimFilePath: String?, // keep this to handle previously saved history + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + var zimReaderSource: ZimReaderSource, val favicon: String?, val historyUrl: String, val historyTitle: String, @@ -37,7 +41,8 @@ data class HistoryEntity( historyItem.databaseId, historyItem.zimId, historyItem.zimName, - historyItem.zimFilePath, + null, // pass null for new history items + historyItem.zimReaderSource, historyItem.favicon, historyItem.historyUrl, historyItem.title, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt index b39de4bd8c..18c45060d1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt @@ -20,14 +20,18 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.PrimaryKey +import io.objectbox.annotation.Convert import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Entity data class HistoryRoomEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, val zimName: String, - val zimFilePath: String, + val zimFilePath: String?, + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + var zimReaderSource: ZimReaderSource?, val favicon: String?, var historyUrl: String, var historyTitle: String, @@ -38,7 +42,8 @@ data class HistoryRoomEntity( historyItem.databaseId, historyItem.zimId, historyItem.zimName, - historyItem.zimFilePath, + null, + historyItem.zimReaderSource, historyItem.favicon, historyItem.historyUrl, historyItem.title, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt index d2f49ea950..5c4cae24a3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt @@ -18,15 +18,19 @@ package org.kiwix.kiwixmobile.core.dao.entities +import io.objectbox.annotation.Convert import io.objectbox.annotation.Entity import io.objectbox.annotation.Id import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Entity data class NotesEntity( @Id var id: Long = 0L, val zimId: String, - var zimFilePath: String?, + var zimFilePath: String?, // keep this to handle previously saved notes + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + var zimReaderSource: ZimReaderSource, val zimUrl: String, var noteTitle: String, var noteFilePath: String, @@ -35,7 +39,8 @@ data class NotesEntity( constructor(item: NoteListItem) : this( id = item.databaseId, zimId = item.zimId, - zimFilePath = item.zimFilePath, + zimFilePath = null, // pass null for new notes + zimReaderSource = item.zimReaderSource, zimUrl = item.zimUrl, noteTitle = item.title, noteFilePath = item.noteFilePath, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt index ac54c7fb83..5bc7c07d4e 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt @@ -21,14 +21,18 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey +import io.objectbox.annotation.Convert import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @Entity(indices = [Index(value = ["noteTitle"], unique = true)]) data class NotesRoomEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, - var zimFilePath: String?, + var zimFilePath: String?, // keep this to handle previously saved notes + @Convert(converter = ZimSourceConverter::class, dbType = String::class) + var zimReaderSource: ZimReaderSource?, val zimUrl: String, var noteTitle: String, var noteFilePath: String, @@ -37,7 +41,8 @@ data class NotesRoomEntity( constructor(item: NoteListItem) : this( id = item.databaseId, zimId = item.zimId, - zimFilePath = item.zimFilePath, + zimFilePath = null, + zimReaderSource = item.zimReaderSource, zimUrl = item.zimUrl, noteTitle = item.title, noteFilePath = item.noteFilePath, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/adapter/Page.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/adapter/Page.kt index 0f524d9838..10802af8e5 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/adapter/Page.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/adapter/Page.kt @@ -18,12 +18,14 @@ package org.kiwix.kiwixmobile.core.page.adapter +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource + interface PageRelated { val id: Long } interface Page : PageRelated { - val zimFilePath: String? + val zimReaderSource: ZimReaderSource? val zimId: String val url: String val title: String diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/BookmarkItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/BookmarkItem.kt index 2bf0670e77..473c3f4acb 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/BookmarkItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/BookmarkItem.kt @@ -21,12 +21,13 @@ package org.kiwix.kiwixmobile.core.page.bookmark.adapter import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource data class BookmarkItem( val databaseId: Long = 0L, override val zimId: String, val zimName: String, - override val zimFilePath: String?, + override val zimReaderSource: ZimReaderSource?, val bookmarkUrl: String, override val title: String, override val favicon: String?, @@ -38,7 +39,7 @@ data class BookmarkItem( entity.id, entity.zimId, entity.zimName, - entity.zimFilePath, + entity.zimReaderSource, entity.bookmarkUrl, entity.bookmarkTitle, entity.favicon @@ -51,7 +52,7 @@ data class BookmarkItem( ) : this( zimId = zimFileReader.id, zimName = zimFileReader.name, - zimFilePath = zimFileReader.zimFile?.canonicalPath ?: zimFileReader.assetDescriptorFilePath, + zimReaderSource = zimFileReader.zimReaderSource, bookmarkUrl = url, title = title, favicon = zimFileReader.favicon diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt index 4b7cf6ef61..6a818ac6f8 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt @@ -21,6 +21,7 @@ package org.kiwix.kiwixmobile.core.page.bookmark.adapter import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.libkiwix.Book import org.kiwix.libkiwix.Bookmark import java.util.UUID @@ -29,7 +30,8 @@ data class LibkiwixBookmarkItem( val databaseId: Long = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE, override val zimId: String, val zimName: String, - override val zimFilePath: String?, + val zimFilePath: String?, + override val zimReaderSource: ZimReaderSource?, val bookmarkUrl: String, override val title: String, override val favicon: String?, @@ -41,11 +43,12 @@ data class LibkiwixBookmarkItem( constructor( libkiwixBookmark: Bookmark, favicon: String?, - zimFilePath: String? + zimReaderSource: ZimReaderSource? ) : this( zimId = libkiwixBookmark.bookId, zimName = libkiwixBookmark.bookTitle, - zimFilePath = zimFilePath, + zimFilePath = zimReaderSource?.toDatabase(), + zimReaderSource = null, bookmarkUrl = libkiwixBookmark.url, title = libkiwixBookmark.title, favicon = favicon, @@ -58,7 +61,8 @@ data class LibkiwixBookmarkItem( zimFileReader: ZimFileReader, libKiwixBook: Book ) : this( - zimFilePath = zimFileReader.zimFile?.canonicalPath, + zimFilePath = zimFileReader.zimReaderSource.toDatabase(), + zimReaderSource = null, zimId = libKiwixBook.id, zimName = libKiwixBook.name, bookmarkUrl = articleUrl, @@ -72,7 +76,8 @@ data class LibkiwixBookmarkItem( libkiwixBook: Book? ) : this( zimId = bookmarkEntity.zimId, - zimFilePath = bookmarkEntity.zimFilePath, + zimFilePath = bookmarkEntity.zimReaderSource?.toDatabase(), + zimReaderSource = null, zimName = bookmarkEntity.zimName, bookmarkUrl = bookmarkEntity.bookmarkUrl, title = bookmarkEntity.bookmarkTitle, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt index a51ad97a49..686c080825 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt @@ -22,6 +22,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.adapter.PageRelated import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource sealed class HistoryListItem : PageRelated { @@ -29,7 +30,7 @@ sealed class HistoryListItem : PageRelated { val databaseId: Long = 0L, override val zimId: String, val zimName: String, - override val zimFilePath: String, + override val zimReaderSource: ZimReaderSource, override val favicon: String?, val historyUrl: String, override val title: String, @@ -49,9 +50,7 @@ sealed class HistoryListItem : PageRelated { ) : this( zimId = zimFileReader.id, zimName = zimFileReader.name, - zimFilePath = zimFileReader.zimFile?.canonicalPath - ?: zimFileReader.assetDescriptorFilePath - ?: "", + zimReaderSource = zimFileReader.zimReaderSource, favicon = zimFileReader.favicon, historyUrl = url, title = title, @@ -63,7 +62,7 @@ sealed class HistoryListItem : PageRelated { historyEntity.id, historyEntity.zimId, historyEntity.zimName, - historyEntity.zimFilePath, + historyEntity.zimReaderSource, historyEntity.favicon, historyEntity.historyUrl, historyEntity.historyTitle, @@ -76,7 +75,7 @@ sealed class HistoryListItem : PageRelated { historyRoomEntity.id, historyRoomEntity.zimId, historyRoomEntity.zimName, - historyRoomEntity.zimFilePath, + historyRoomEntity.zimReaderSource, historyRoomEntity.favicon, historyRoomEntity.historyUrl, historyRoomEntity.historyTitle, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt index cb24a152a7..c1b6cac59e 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/adapter/NoteListItem.kt @@ -4,12 +4,13 @@ import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource data class NoteListItem( val databaseId: Long = 0L, override val zimId: String, override val title: String, - override val zimFilePath: String?, + override val zimReaderSource: ZimReaderSource?, val zimUrl: String, val noteFilePath: String, override val favicon: String?, @@ -22,7 +23,7 @@ data class NoteListItem( notesEntity.id, notesEntity.zimId, notesEntity.noteTitle, - notesEntity.zimFilePath, + notesEntity.zimReaderSource, notesEntity.zimUrl, notesEntity.noteFilePath, notesEntity.favicon @@ -36,7 +37,7 @@ data class NoteListItem( ) : this( zimId = zimFileReader.id, title = title, - zimFilePath = zimFileReader.zimFile?.canonicalPath ?: zimFileReader.assetDescriptorFilePath, + zimReaderSource = zimFileReader.zimReaderSource, zimUrl = url, favicon = zimFileReader.favicon, noteFilePath = noteFilePath @@ -46,7 +47,7 @@ data class NoteListItem( notesRoomEntity.id, notesRoomEntity.zimId, notesRoomEntity.noteTitle, - notesRoomEntity.zimFilePath, + notesRoomEntity.zimReaderSource, notesRoomEntity.zimUrl, notesRoomEntity.noteFilePath, notesRoomEntity.favicon diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt index 010c80b1f6..34523b7381 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt @@ -22,6 +22,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.zim_manager.KiwixTag import java.io.File import java.util.Locale @@ -43,7 +44,7 @@ sealed class BooksOnDiskListItem { data class BookOnDisk constructor( val databaseId: Long = 0L, val book: Book, - val file: File, + val zimReaderSource: ZimReaderSource, val tags: List = KiwixTag.from(book.tags), override val id: Long = databaseId ) : BooksOnDiskListItem() { @@ -55,17 +56,17 @@ sealed class BooksOnDiskListItem { constructor(bookOnDiskEntity: BookOnDiskEntity) : this( bookOnDiskEntity.id, bookOnDiskEntity.toBook(), - bookOnDiskEntity.file + bookOnDiskEntity.zimReaderSource ) constructor(downloadRoomEntity: DownloadRoomEntity) : this( book = downloadRoomEntity.toBook(), - file = File(downloadRoomEntity.file) + zimReaderSource = ZimReaderSource(File(downloadRoomEntity.file)) ) - constructor(file: File, zimFileReader: ZimFileReader) : this( + constructor(zimFileReader: ZimFileReader) : this( book = zimFileReader.toBook(), - file = file + zimReaderSource = zimFileReader.zimReaderSource ) } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt index bca1df4d16..053bc2d27c 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt @@ -86,7 +86,7 @@ fun bookmark( id = id, zimId = zimId, zimName = zimName, - zimFilePath = zimFilePath, + zim = zimFilePath, bookmarkUrl = bookmarkUrl, title = bookmarkTitle, isSelected = isSelected, From 811e37bf701507747e06e0dea4b380489526796a Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 16:03:44 +0530 Subject: [PATCH 04/19] Refactored the whole code to use ZimReaderSource --- .../ObjectBoxToLibkiwixMigratorTest.kt | 12 +++- .../kiwixmobile/mimetype/MimeTypeTest.kt | 11 ++- .../kiwixmobile/reader/EncodedUrlTest.kt | 11 ++- .../kiwixmobile/main/KiwixMainActivity.kt | 2 +- .../library/LocalLibraryFragment.kt | 5 +- .../destination/reader/KiwixReaderFragment.kt | 54 +++++++++------ .../fileselectView/effects/DeleteFiles.kt | 13 ++-- .../effects/OpenFileWithNavigation.kt | 10 +-- .../fileselectView/effects/ShareFiles.kt | 7 +- .../kiwix/kiwixmobile/core/StorageObserver.kt | 5 +- .../kiwixmobile/core/dao/LibkiwixBookmarks.kt | 1 - .../kiwixmobile/core/error/ErrorActivity.kt | 2 +- .../kiwixmobile/core/main/AddNoteDialog.kt | 2 +- .../kiwixmobile/core/main/CoreMainActivity.kt | 13 +++- .../core/main/CoreReaderFragment.kt | 68 ++++++------------- .../page/history/adapter/HistoryListItem.kt | 2 +- .../viewmodel/effects/ShowOpenNoteDialog.kt | 17 ++--- .../core/page/viewmodel/effects/OpenPage.kt | 4 +- .../core/reader/ZimReaderSource.kt | 2 +- .../kiwixmobile/core/utils/files/FileUtils.kt | 47 +++++++++++++ .../kiwixmobile/core/webserver/KiwixServer.kt | 2 +- .../core/webserver/ZimHostFragment.kt | 4 +- 22 files changed, 173 insertions(+), 121 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToLibkiwixMigratorTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToLibkiwixMigratorTest.kt index db5b32daa4..1698b6a879 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToLibkiwixMigratorTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToLibkiwixMigratorTest.kt @@ -43,6 +43,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity import org.kiwix.kiwixmobile.core.data.remote.ObjectBoxToLibkiwixMigrator import org.kiwix.kiwixmobile.core.di.modules.DatabaseModule import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.main.KiwixMainActivity @@ -74,6 +75,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { expectedZimId, expectedZimName, expectedZimFilePath, + ZimReaderSource(File(expectedZimFilePath)), expectedBookmarkUrl, expectedTitle, expectedFavicon @@ -156,7 +158,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { val actualDataAfterMigration = objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst() assertEquals(1, actualDataAfterMigration.size) - assertEquals(actualDataAfterMigration[0].zimFilePath, expectedZimFilePath) + assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), expectedZimFilePath) assertEquals(actualDataAfterMigration[0].zimId, expectedZimId) assertEquals(actualDataAfterMigration[0].title, expectedTitle) assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl) @@ -185,6 +187,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { expectedZimId, expectedZimName, expectedZimFilePath, + ZimReaderSource(File(expectedZimFilePath)), existingBookmarkUrl, existingTitle, expectedFavicon @@ -226,6 +229,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { expectedZimId, expectedZimName, expectedZimFilePath, + ZimReaderSource(File(expectedZimFilePath)), "https://alpine_linux/search_$i", "title_$i", expectedFavicon @@ -250,6 +254,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { expectedZimId, expectedZimName, null, + null, expectedBookmarkUrl, expectedTitle, expectedFavicon @@ -261,7 +266,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { val actualDataAfterMigration = objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst() assertEquals(1, actualDataAfterMigration.size) - assertEquals(actualDataAfterMigration[0].zimFilePath, null) + assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), null) assertEquals(actualDataAfterMigration[0].zimId, expectedZimId) assertEquals(actualDataAfterMigration[0].title, expectedTitle) assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl) @@ -278,6 +283,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { expectedZimId, expectedZimName, nonExistingPath, + ZimReaderSource(File(nonExistingPath)), expectedBookmarkUrl, expectedTitle, expectedFavicon @@ -289,7 +295,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() { val actualDataAfterMigration = objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst() assertEquals(1, actualDataAfterMigration.size) - assertEquals(actualDataAfterMigration[0].zimFilePath, null) + assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), null) assertEquals(actualDataAfterMigration[0].zimId, expectedZimId) assertEquals(actualDataAfterMigration[0].title, expectedTitle) assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt index 72b67a4fc2..47cf9c6e0b 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/mimetype/MimeTypeTest.kt @@ -31,11 +31,11 @@ import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.main.KiwixMainActivity import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible -import org.kiwix.libzim.Archive import org.kiwix.libzim.SuggestionSearcher import java.io.File import java.io.FileOutputStream @@ -81,12 +81,11 @@ class MimeTypeTest : BaseActivityTest() { } } } - val archive = Archive(zimFile.canonicalPath) + val zimSource = ZimReaderSource(zimFile) + val archive = zimSource.createArchive() val zimFileReader = ZimFileReader( - zimFile, - emptyList(), - null, - archive, + zimSource, + archive!!, DarkModeConfig(SharedPreferenceUtil(context), context), SuggestionSearcher(archive) ) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/EncodedUrlTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/EncodedUrlTest.kt index 35e1c208e2..e92c9abf22 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/EncodedUrlTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/EncodedUrlTest.kt @@ -31,11 +31,11 @@ import org.junit.Test import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.main.KiwixMainActivity import org.kiwix.kiwixmobile.testutils.TestUtils -import org.kiwix.libzim.Archive import org.kiwix.libzim.SuggestionSearcher import java.io.File import java.io.FileOutputStream @@ -89,12 +89,11 @@ class EncodedUrlTest : BaseActivityTest() { } } } - val archive = Archive(zimFile.canonicalPath) + val zimReaderSource = ZimReaderSource(zimFile) + val archive = zimReaderSource.createArchive() val zimFileReader = ZimFileReader( - zimFile, - emptyList(), - null, - archive, + zimReaderSource, + archive!!, DarkModeConfig(SharedPreferenceUtil(context), context), SuggestionSearcher(archive) ) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt index d84f309204..89f11a8654 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt @@ -220,7 +220,7 @@ class KiwixMainActivity : CoreMainActivity() { { intent.getStringExtra(DOWNLOAD_NOTIFICATION_TITLE)?.let { newBookDao.bookMatching(it)?.let { bookOnDiskEntity -> - openZimFromFilePath(bookOnDiskEntity.file.path) + openZimFromFilePath(bookOnDiskEntity.zimReaderSource.toDatabase()) } } }, diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt index 75509dfaac..6fe6c1f9e8 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt @@ -75,6 +75,7 @@ import org.kiwix.kiwixmobile.core.main.MainRepositoryActions import org.kiwix.kiwixmobile.core.navigateToAppSettings import org.kiwix.kiwixmobile.core.navigateToSettings import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener @@ -405,9 +406,9 @@ class LocalLibraryFragment : BaseFragment() { // we can directly add it to the database. // See https://github.com/kiwix/kiwix-android/issues/3650 runBlocking { - zimReaderFactory.create(file) + zimReaderFactory.create(ZimReaderSource(file)) ?.let { zimFileReader -> - BookOnDisk(file, zimFileReader).also { + BookOnDisk(zimFileReader).also { mainRepositoryActions.saveBook(it) zimFileReader.dispose() } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index 8749a2600e..5642d07318 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -54,11 +54,14 @@ import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.CoreReaderFragment import org.kiwix.kiwixmobile.core.main.CoreWebViewClient import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX import org.kiwix.kiwixmobile.core.utils.files.FileUtils import org.kiwix.kiwixmobile.core.utils.files.Log +import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem import java.io.File private const val HIDE_TAB_SWITCHER_DELAY: Long = 300 @@ -124,7 +127,7 @@ class KiwixReaderFragment : CoreReaderFragment() { activity.toast(string.error_file_not_found) return } - openZimFile(File(filePath)) + openZimFile(ZimReaderSource(File(filePath))) } override fun loadDrawerViews() { @@ -200,9 +203,7 @@ class KiwixReaderFragment : CoreReaderFragment() { override fun onResume() { super.onResume() - if (zimReaderContainer?.zimFile == null && - zimReaderContainer?.zimFileReader?.assetFileDescriptorList?.isEmpty() == true - ) { + if (zimReaderContainer?.zimReaderSource == null) { exitBook() } if (isFullScreenVideo || isInFullScreenMode()) { @@ -221,14 +222,14 @@ class KiwixReaderFragment : CoreReaderFragment() { currentTab: Int ) { val settings = requireActivity().getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0) - val zimFile = settings.getString(TAG_CURRENT_FILE, null) + val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null)) - if (zimFile != null && File(zimFile).isFileExist()) { - if (zimReaderContainer?.zimFile == null) { - openZimFile(File(zimFile)) + if (zimReaderSource != null && zimReaderSource.canOpenInLibkiwix()) { + if (zimReaderContainer?.zimReaderSource == null) { + openZimFile(zimReaderSource) Log.d( TAG_KIWIX, - "Kiwix normal start, Opened last used zimFile: -> $zimFile" + "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}" ) } else { zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) @@ -305,21 +306,13 @@ class KiwixReaderFragment : CoreReaderFragment() { when (it.scheme) { "file" -> { Handler(Looper.getMainLooper()).postDelayed({ - openZimFile(it.toFile()).also { - // if used once then clear it to avoid affecting any other functionality - // of the application. - requireActivity().intent.action = null - } + openAndSaveZimFileInLocalLibrary(it.toFile()) }, 300) } "content" -> { Handler(Looper.getMainLooper()).postDelayed({ - getZimFileFromUri(it)?.let { zimFile -> - openZimFile(zimFile) - }.also { - requireActivity().intent.action = null - } + getZimFileFromUri(it)?.let(::openAndSaveZimFileInLocalLibrary) }, 300) } @@ -329,6 +322,29 @@ class KiwixReaderFragment : CoreReaderFragment() { return ShouldCall } + private fun openAndSaveZimFileInLocalLibrary(file: File) { + val zimReaderSource = ZimReaderSource(file) + if (zimReaderSource.canOpenInLibkiwix()) { + zimReaderContainer?.let { zimReaderContainer -> + zimReaderContainer.setZimReaderSource(zimReaderSource) + + zimReaderContainer.zimFileReader?.let { zimFileReader -> + BooksOnDiskListItem.BookOnDisk(zimFileReader).also { bookOnDisk -> + // save the book in the library + repositoryActions?.saveBook(bookOnDisk) + zimFileReader.dispose() + } + } + } + openZimFile(ZimReaderSource(file)) + } else { + activity.toast(R.string.cannot_open_file) + } + // if used once then clear it to avoid affecting any other functionality + // of the application. + requireActivity().intent.action = null + } + private fun getZimFileFromUri( uri: Uri ): File? { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/DeleteFiles.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/DeleteFiles.kt index c559997e28..576aad09ec 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/DeleteFiles.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/DeleteFiles.kt @@ -59,17 +59,20 @@ data class DeleteFiles(private val booksOnDiskListItems: List) : private fun List.deleteAll(): Boolean { return fold(true) { acc, book -> acc && deleteSpecificZimFile(book).also { - if (it && book.file.canonicalPath == zimReaderContainer.zimCanonicalPath) { - zimReaderContainer.setZimFile(null) + if (it && book.zimReaderSource == zimReaderContainer.zimReaderSource) { + zimReaderContainer.setZimReaderSource(null) } } } } private fun deleteSpecificZimFile(book: BookOnDisk): Boolean { - val file = book.file - FileUtils.deleteZimFile(file.path) - if (file.isFileExist()) { + val file = book.zimReaderSource.file + file?.let { + @Suppress("UnreachableCode") + FileUtils.deleteZimFile(it.path) + } + if (file?.isFileExist() == true) { return false } newBookDao.delete(book.databaseId) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt index 5c07ba8d9c..43eb6aed8f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt @@ -19,11 +19,9 @@ package org.kiwix.kiwixmobile.zimManager.fileselectView.effects import androidx.appcompat.app.AppCompatActivity -import androidx.core.net.toUri import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate -import org.kiwix.kiwixmobile.core.extensions.canReadFile import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem import org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader @@ -32,12 +30,14 @@ data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.Bo SideEffect { override fun invokeWith(activity: AppCompatActivity) { - val file = bookOnDisk.file - if (!file.canReadFile()) { + val zimReaderSource = bookOnDisk.zimReaderSource + if (!zimReaderSource.canOpenInLibkiwix()) { activity.toast(R.string.error_file_not_found) } else { activity.navigate( - actionNavigationLibraryToNavigationReader().apply { zimFileUri = file.toUri().toString() } + actionNavigationLibraryToNavigationReader().apply { + zimFileUri = zimReaderSource.toDatabase() + } ) } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt index 33f0e9546c..5945220b22 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt @@ -19,7 +19,6 @@ package org.kiwix.kiwixmobile.zimManager.fileselectView.effects import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.FileProvider import androidx.core.os.bundleOf import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.core.base.SideEffect @@ -31,11 +30,7 @@ data class ShareFiles(private val selectedBooks: List) : SideEffect { override fun invokeWith(activity: AppCompatActivity) { val selectedFileContentURIs = selectedBooks.mapNotNull { - FileProvider.getUriForFile( - activity, - activity.packageName + ".fileprovider", - it.file - ) + it.zimReaderSource.getUri(activity) } activity.navigate( R.id.localFileTransferFragment, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/StorageObserver.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/StorageObserver.kt index 3a67ac8c3d..68cfe4b7c9 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/StorageObserver.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/StorageObserver.kt @@ -26,6 +26,7 @@ import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.files.FileSearch import org.kiwix.kiwixmobile.core.utils.files.ScanningProgressListener import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk @@ -57,9 +58,9 @@ class StorageObserver @Inject constructor( downloads.firstOrNull { file.absolutePath.endsWith(it.fileNameFromUrl) } == null private fun convertToBookOnDisk(file: File) = runBlocking { - zimReaderFactory.create(file) + zimReaderFactory.create(ZimReaderSource(file)) ?.let { zimFileReader -> - BookOnDisk(file, zimFileReader).also { + BookOnDisk(zimFileReader).also { // add the book to libkiwix library to validate the imported bookmarks libkiwixBookmarks.addBookToLibrary(archive = zimFileReader.jniKiwixReader) zimFileReader.dispose() 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 2659eef219..cebfb30ac3 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 @@ -36,7 +36,6 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.page.adapter.Page -import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE import org.kiwix.kiwixmobile.core.reader.ZimFileReader diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/error/ErrorActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/error/ErrorActivity.kt index 92cc46b0f7..f1002a074d 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/error/ErrorActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/error/ErrorActivity.kt @@ -149,7 +149,7 @@ open class ErrorActivity : BaseActivity() { } return """ Current Zim File: - ${zimReaderContainer.zimCanonicalPath} + ${zimReaderContainer.zimReaderSource?.toDatabase()} All Zim Files in DB: $allZimFiles diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt index ca9ee04a94..b18b346079 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/AddNoteDialog.kt @@ -119,7 +119,7 @@ class AddNoteDialog : DialogFragment() { .inject(this) // Returns name of the form ".../Kiwix/granbluefantasy_en_all_all_nopic_2018-10.zim" - zimFileName = zimReaderContainer.zimCanonicalPath ?: zimReaderContainer.name + zimFileName = zimReaderContainer.zimReaderSource?.toDatabase() ?: zimReaderContainer.name if (zimFileName != null) { // No zim file currently opened zimFileTitle = zimReaderContainer.zimFileTitle zimId = zimReaderContainer.id.orEmpty() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index dddb860842..86467bf14a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -57,6 +57,7 @@ import org.kiwix.kiwixmobile.core.extensions.getToolbarNavigationIcon import org.kiwix.kiwixmobile.core.extensions.registerReceiver import org.kiwix.kiwixmobile.core.extensions.setToolTipWithContentDescription import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.search.NAV_ARG_SEARCH_STRING import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE import org.kiwix.kiwixmobile.core.utils.ExternalLinkOpener @@ -372,12 +373,20 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { ) } - fun openPage(pageUrl: String, zimFilePath: String = "", shouldOpenInNewTab: Boolean = false) { + fun openPage( + pageUrl: String, + zimReaderSource: ZimReaderSource? = null, + shouldOpenInNewTab: Boolean = false + ) { + var zimFileUri = "" + if (zimReaderSource != null) { + zimFileUri = zimReaderSource.toDatabase() + } navigate( readerFragmentResId, bundleOf( PAGE_URL_KEY to pageUrl, - ZIM_FILE_URI_KEY to zimFilePath, + ZIM_FILE_URI_KEY to zimFileUri, SHOULD_OPEN_IN_NEW_TAB to shouldOpenInNewTab ) ) 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 5d9d3e5176..2916d03eb6 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 @@ -26,7 +26,6 @@ import android.content.Intent import android.content.ServiceConnection import android.content.SharedPreferences import android.content.pm.PackageManager -import android.content.res.AssetFileDescriptor import android.content.res.Configuration import android.graphics.Canvas import android.media.AudioManager @@ -107,7 +106,6 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.requestNotificat import org.kiwix.kiwixmobile.core.extensions.ViewGroupExtensions.findFirstTextView import org.kiwix.kiwixmobile.core.extensions.closeFullScreenMode import org.kiwix.kiwixmobile.core.extensions.getToolbarNavigationIcon -import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.extensions.setToolTipWithContentDescription import org.kiwix.kiwixmobile.core.extensions.showFullScreenMode import org.kiwix.kiwixmobile.core.extensions.snack @@ -131,6 +129,7 @@ import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_S import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Companion.CONTENT_PREFIX import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen import org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate import org.kiwix.kiwixmobile.core.utils.DimenUtils.getToolbarHeight @@ -159,7 +158,6 @@ import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.kiwixmobile.core.utils.titleToUrl import org.kiwix.kiwixmobile.core.utils.urlSuffixToParsableUrl import org.kiwix.libkiwix.Book -import java.io.File import java.io.IOException import java.text.SimpleDateFormat import java.util.Date @@ -286,11 +284,11 @@ abstract class CoreReaderFragment : private var tts: KiwixTextToSpeech? = null private var compatCallback: CompatFindActionModeCallback? = null private var tabsAdapter: TabsAdapter? = null - private var file: File? = null + private var zimReaderSource: ZimReaderSource? = null private var actionMode: ActionMode? = null private var tempWebViewForUndo: KiwixWebView? = null private var tempWebViewListForUndo: MutableList = ArrayList() - private var tempZimFileForUndo: File? = null + private var tempZimSourceForUndo: ZimReaderSource? = null private var isFirstRun = false private var tableDrawerAdapter: TableDrawerAdapter? = null private var tableDrawerRight: RecyclerView? = null @@ -1323,7 +1321,7 @@ abstract class CoreReaderFragment : // Address those issues when the user frequently clicks on the close icon of the same tab. // See https://github.com/kiwix/kiwix-android/issues/3790 for more details. if (index == RecyclerView.NO_POSITION) return - tempZimFileForUndo = zimReaderContainer?.zimFile + tempZimSourceForUndo = zimReaderContainer?.zimReaderSource tempWebViewForUndo = webViewList[index] webViewList.removeAt(index) if (index <= currentWebViewIndex && currentWebViewIndex > 0) { @@ -1360,7 +1358,7 @@ abstract class CoreReaderFragment : } private fun closeZimBook() { - zimReaderContainer?.setZimFile(null) + zimReaderContainer?.setZimReaderSource(null) } private fun restoreDeletedTab(index: Int) { @@ -1378,7 +1376,7 @@ abstract class CoreReaderFragment : LinearLayout.LayoutParams.MATCH_PARENT ) } - zimReaderContainer?.setZimFile(tempZimFileForUndo) + zimReaderContainer?.setZimReaderSource(tempZimSourceForUndo) webViewList.add(index, it) tabsAdapter?.notifyDataSetChanged() snackBarRoot?.let { root -> @@ -1617,33 +1615,21 @@ abstract class CoreReaderFragment : unsupportedMimeTypeHandler?.showSaveOrOpenUnsupportedFilesDialog(url, documentType) } - fun openZimFile( - file: File?, - isCustomApp: Boolean = false, - assetFileDescriptorList: List = emptyList(), - filePath: String? = null - ) { + fun openZimFile(zimReaderSource: ZimReaderSource, isCustomApp: Boolean = false) { if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) || isCustomApp) { - if (file?.isFileExist() == true) { + if (zimReaderSource.canOpenInLibkiwix()) { // Show content if there is `Open Library` button showing // and we are opening the ZIM file reopenBook() - openAndSetInContainer(file = file) - updateTitle() - } else if (assetFileDescriptorList.isNotEmpty()) { - reopenBook() - openAndSetInContainer( - assetFileDescriptorList = assetFileDescriptorList, - filePath = filePath - ) + openAndSetInContainer(zimReaderSource) updateTitle() } else { exitBook() - Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + file?.absolutePath) + Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + zimReaderSource.toDatabase()) requireActivity().toast(R.string.error_file_not_found, Toast.LENGTH_LONG) } } else { - this.file = file + this.zimReaderSource = zimReaderSource requestExternalStoragePermission() } } @@ -1666,27 +1652,16 @@ abstract class CoreReaderFragment : ) } - private fun openAndSetInContainer( - file: File? = null, - assetFileDescriptorList: List = emptyList(), - filePath: String? = null - ) { + private fun openAndSetInContainer(zimReaderSource: ZimReaderSource) { try { - if (isNotPreviouslyOpenZim(file?.canonicalPath)) { + if (isNotPreviouslyOpenZim(zimReaderSource)) { webViewList.clear() } } catch (e: IOException) { e.printStackTrace() } zimReaderContainer?.let { zimReaderContainer -> - if (assetFileDescriptorList.isNotEmpty()) { - zimReaderContainer.setZimFileDescriptor( - assetFileDescriptorList, - filePath = filePath - ) - } else { - zimReaderContainer.setZimFile(file) - } + zimReaderContainer.setZimReaderSource(zimReaderSource) val zimFileReader = zimReaderContainer.zimFileReader zimFileReader?.let { zimFileReader -> @@ -1721,8 +1696,8 @@ abstract class CoreReaderFragment : bookmarkingDisposable?.dispose() } - private fun isNotPreviouslyOpenZim(canonicalPath: String?): Boolean = - canonicalPath != null && canonicalPath != zimReaderContainer?.zimCanonicalPath + private fun isNotPreviouslyOpenZim(zimReaderSource: ZimReaderSource?): Boolean = + zimReaderSource != null && zimReaderSource != zimReaderContainer?.zimReaderSource override fun onRequestPermissionsResult( requestCode: Int, @@ -1732,7 +1707,7 @@ abstract class CoreReaderFragment : when (requestCode) { REQUEST_STORAGE_PERMISSION -> { if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) { - file?.let(::openZimFile) + zimReaderSource?.let(::openZimFile) } else { snackBarRoot?.let { snackBarRoot -> Snackbar.make(snackBarRoot, R.string.request_storage, Snackbar.LENGTH_LONG) @@ -1761,7 +1736,7 @@ abstract class CoreReaderFragment : rotate() setIsCloseAllTabButtonClickable(false) } - tempZimFileForUndo = zimReaderContainer?.zimFile + tempZimSourceForUndo = zimReaderContainer?.zimReaderSource tempWebViewListForUndo.apply { clear() addAll(webViewList) @@ -1788,7 +1763,7 @@ abstract class CoreReaderFragment : private fun restoreDeletedTabs() { if (tempWebViewListForUndo.isNotEmpty()) { - zimReaderContainer?.setZimFile(tempZimFileForUndo) + zimReaderContainer?.setZimReaderSource(tempZimSourceForUndo) webViewList.addAll(tempWebViewListForUndo) tabsAdapter?.notifyDataSetChanged() snackBarRoot?.let { root -> @@ -2131,7 +2106,7 @@ abstract class CoreReaderFragment : urls.put(view.url) positions.put(view.scrollY) } - editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimCanonicalPath) + editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) editor.putString(TAG_CURRENT_ARTICLES, "$urls") editor.putString(TAG_CURRENT_POSITIONS, "$positions") editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) @@ -2143,7 +2118,8 @@ abstract class CoreReaderFragment : saveTabStates() Log.d( TAG_KIWIX, - "onPause Save current zim file to preferences: " + zimReaderContainer?.zimCanonicalPath + "onPause Save current zim file to preferences: " + + "${zimReaderContainer?.zimReaderSource?.toDatabase()}" ) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt index 686c080825..dec22676ff 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/HistoryListItem.kt @@ -30,7 +30,7 @@ sealed class HistoryListItem : PageRelated { val databaseId: Long = 0L, override val zimId: String, val zimName: String, - override val zimReaderSource: ZimReaderSource, + override val zimReaderSource: ZimReaderSource?, override val favicon: String?, val historyUrl: String, override val title: String, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt index d1ce75018d..47d65b9df5 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt @@ -23,6 +23,7 @@ import io.reactivex.processors.PublishProcessor import org.json.JSONArray import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent +import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenNote @@ -36,7 +37,6 @@ import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_POSITIONS import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_TAB import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.ShowNoteDialog -import java.io.File import javax.inject.Inject data class ShowOpenNoteDialog( @@ -52,14 +52,15 @@ data class ShowOpenNoteDialog( { effects.offer(OpenPage(page, zimReaderContainer)) }, { val item = page as NoteListItem - // Check if zimFilePath is not null, and then set it in zimReaderContainer. + // Check if toDatabase is not null, and then set it in zimReaderContainer. // For custom apps, we are currently using fileDescriptor, and they only have a single file in them, // which is already set in zimReaderContainer, so there's no need to set it again. - item.zimFilePath?.let { - val currentZimFilePath = zimReaderContainer.zimCanonicalPath - val file = File(it) - zimReaderContainer.setZimFile(file) - if (zimReaderContainer.zimCanonicalPath != currentZimFilePath) { + item.zimReaderSource?.toDatabase().let { + if (!activity.isCustomApp()) { + zimReaderContainer.setZimReaderSource(item.zimReaderSource) + } + val currentZimReaderSource = zimReaderContainer.zimReaderSource + if (zimReaderContainer.zimReaderSource != currentZimReaderSource) { // if current zim file is not the same set the main page of that zim file // so that when we go back it properly loads the article, and do nothing if the // zim file is same because there might be multiple tabs opened. @@ -72,7 +73,7 @@ data class ShowOpenNoteDialog( val positions = JSONArray() urls.put(CONTENT_PREFIX + zimReaderContainer.mainPage) positions.put(0) - editor.putString(TAG_CURRENT_FILE, zimReaderContainer.zimCanonicalPath) + editor.putString(TAG_CURRENT_FILE, zimReaderContainer.zimReaderSource?.toDatabase()) editor.putString(TAG_CURRENT_ARTICLES, "$urls") editor.putString(TAG_CURRENT_POSITIONS, "$positions") editor.putInt(TAG_CURRENT_TAB, 0) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPage.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPage.kt index 89e7c400c4..663c303052 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPage.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPage.kt @@ -32,8 +32,8 @@ data class OpenPage( override fun invokeWith(activity: AppCompatActivity) { activity as CoreMainActivity activity.popNavigationBackstack() - if (page.zimFilePath != zimReaderContainer.zimCanonicalPath) { - page.zimFilePath?.let { activity.openPage(page.url, it) } + if (page.zimReaderSource != zimReaderContainer.zimReaderSource) { + page.zimReaderSource?.let { activity.openPage(page.url, it) } } else { activity.openPage(page.url) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt index f9e7cd25a8..f52a80e9f3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/reader/ZimReaderSource.kt @@ -35,7 +35,7 @@ import java.io.File class ZimReaderSource( val file: File? = null, val uri: Uri? = null, - private val assetFileDescriptorList: List? = null + val assetFileDescriptorList: List? = null ) { constructor(uri: Uri) : this( uri = uri, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt index cc48cfe89b..2fd010492b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt @@ -22,6 +22,7 @@ import android.app.Activity import android.content.ContentUris import android.content.Context import android.content.Intent +import android.content.res.AssetFileDescriptor import android.net.Uri import android.os.Build import android.os.Environment @@ -44,6 +45,8 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import java.io.BufferedReader import java.io.File +import java.io.FileInputStream +import java.io.FileNotFoundException import java.io.IOException object FileUtils { @@ -476,4 +479,48 @@ object FileUtils { @JvmStatic fun getDemoFilePathForCustomApp(context: Context) = "${ContextCompat.getExternalFilesDirs(context, null)[0]}/demo.zim" + + @SuppressLint("Recycle") + @JvmStatic + fun getAssetFileDescriptorFromUri( + context: Context, + uri: Uri + ): List? { + return try { + val assetFileDescriptor = context.contentResolver.openAssetFileDescriptor(uri, "r") + // Verify whether libkiwix can successfully open this file descriptor or not. + return if ( + isFileDescriptorCanOpenWithLibkiwix(assetFileDescriptor?.parcelFileDescriptor?.fd) + ) { + assetFileDescriptor?.let(::listOf) + } else { + null + } + } catch (ignore: FileNotFoundException) { + null + } catch (ignore: Exception) { + // It may throw a SecurityException in the Play Store variant + // since we have limited access to storage and URIs in the Play Store variant. + // If the user opens the ZIM file via app linking and closes the application, + // the next time they try to open that ZIM file, we won't have access to this URI. + null + } + } + + @JvmStatic + fun isFileDescriptorCanOpenWithLibkiwix(fdNumber: Int?): Boolean { + return try { + // Attempt to create a FileInputStream object using the specified path. + // Since libkiwix utilizes this path to create the archive object internally, + // it is crucial to verify if we can successfully read the file descriptor (fd) + // via the given file path before passing it to libkiwix. + // This precaution helps prevent runtime crashes. + // For more details, refer to https://github.com/kiwix/kiwix-android/pull/3636. + FileInputStream("dev/fd/$fdNumber") + true + } catch (ignore: Exception) { + ignore.printStackTrace() + false + } + } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt index 94754e6134..820058683b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/KiwixServer.kt @@ -52,7 +52,7 @@ class KiwixServer @Inject constructor( val archive = if (path == getDemoFilePathForCustomApp(context)) { // For custom apps using a demo file, create an Archive with FileDescriptor val assetFileDescriptor = - zimReaderContainer.zimFileReader?.assetFileDescriptorList?.get(0) + zimReaderContainer.zimReaderSource?.assetFileDescriptorList?.get(0) val startOffset = assetFileDescriptor?.startOffset ?: 0L val size = assetFileDescriptor?.length ?: 0L Archive( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt index 7db14824cd..995d4338e1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/webserver/ZimHostFragment.kt @@ -117,7 +117,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { .filter(BooksOnDiskListItem::isSelected) .filterIsInstance() .map { - it.file.absolutePath + it.zimReaderSource.toDatabase() } .onEach { path -> Log.v(tag, "ZIM PATH : $path") @@ -487,7 +487,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { if (it is BookOnDisk) { zimReaderContainer.zimFileReader?.let { zimFileReader -> val booksOnDiskListItem = - (BookOnDisk(it.file, zimFileReader) as BooksOnDiskListItem) + (BookOnDisk(zimFileReader) as BooksOnDiskListItem) .apply { isSelected = true } From 6f2c3a45cfe01486e19eb32f3d0bf45e9f5a0ad8 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 17:18:48 +0530 Subject: [PATCH 05/19] Fixed the test cases and some code --- core/objectbox-models/default.json | 36 +++-- core/objectbox-models/default.json.bak | 140 +++--------------- .../core/dao/entities/HistoryRoomEntity.kt | 16 +- .../core/data/KiwixRoomDatabase.kt | 3 +- .../sharedFunctions/TestModelFunctions.kt | 11 +- .../kiwixmobile/core/StorageObserverTest.kt | 8 +- .../kiwixmobile/core/dao/HistoryDaoTest.kt | 11 +- .../kiwixmobile/core/dao/NewBookDaoTest.kt | 51 ++++--- .../core/dao/NewBookmarksDaoTest.kt | 5 +- .../kiwixmobile/core/dao/NewNoteDaoTest.kt | 5 +- .../kiwixmobile/core/page/PageTestHelpers.kt | 63 +++++++- .../bookmark/viewmodel/BookmarkStateTest.kt | 17 ++- .../viewmodel/BookmarkViewModelTest.kt | 40 +++-- .../effects/ShowDeleteBookmarksDialogTest.kt | 12 +- .../history/viewmodel/HistoryStateTest.kt | 26 +++- .../history/viewmodel/HistoryViewModelTest.kt | 53 ++++++- .../effects/ShowDeleteHistoryDialogTest.kt | 2 +- .../core/page/viewmodel/PageStateTest.kt | 24 ++- .../core/page/viewmodel/PageViewModelTest.kt | 34 ++++- .../viewmodel/effects/DeletePageItemsTest.kt | 6 +- .../page/viewmodel/effects/OpenPageTest.kt | 10 +- .../custom/main/CustomReaderFragment.kt | 18 ++- 22 files changed, 363 insertions(+), 228 deletions(-) diff --git a/core/objectbox-models/default.json b/core/objectbox-models/default.json index 9c418ee2c1..28ded888e3 100644 --- a/core/objectbox-models/default.json +++ b/core/objectbox-models/default.json @@ -5,7 +5,7 @@ "entities": [ { "id": "3:5536749840871435068", - "lastPropertyId": "17:2701677664876214591", + "lastPropertyId": "18:1711250046418389186", "name": "BookOnDiskEntity", "properties": [ { @@ -14,11 +14,6 @@ "type": 6, "flags": 1 }, - { - "id": "2:2644395282642821815", - "name": "file", - "type": 9 - }, { "id": "4:3145196313443812205", "name": "bookId", @@ -88,6 +83,11 @@ "id": "17:2701677664876214591", "name": "tags", "type": 9 + }, + { + "id": "18:1711250046418389186", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -123,7 +123,7 @@ }, { "id": "5:3222423958972105425", - "lastPropertyId": "10:8395372122440621469", + "lastPropertyId": "11:6493253695033019145", "name": "HistoryEntity", "properties": [ { @@ -171,13 +171,18 @@ "id": "10:8395372122440621469", "name": "dateString", "type": 9 + }, + { + "id": "11:6493253695033019145", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] }, { "id": "6:2737311997994502758", - "lastPropertyId": "7:3805929017981932900", + "lastPropertyId": "8:7455000637355817969", "name": "BookmarkEntity", "properties": [ { @@ -215,6 +220,11 @@ "id": "7:3805929017981932900", "name": "favicon", "type": 9 + }, + { + "id": "8:7455000637355817969", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -250,7 +260,7 @@ }, { "id": "10:3205842982118792800", - "lastPropertyId": "9:5286545520416917562", + "lastPropertyId": "10:8943937679373521794", "name": "NotesEntity", "properties": [ { @@ -288,6 +298,11 @@ "id": "9:5286545520416917562", "name": "zimUrl", "type": 9 + }, + { + "id": "10:8943937679373521794", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -378,7 +393,8 @@ 5555873126720275555, 2724607601244650879, 5485468735259326535, - 4272820830206771469 + 4272820830206771469, + 2644395282642821815 ], "retiredRelationUids": [], "version": 1 diff --git a/core/objectbox-models/default.json.bak b/core/objectbox-models/default.json.bak index 6a46ca54c7..9c418ee2c1 100644 --- a/core/objectbox-models/default.json.bak +++ b/core/objectbox-models/default.json.bak @@ -248,120 +248,6 @@ ], "relations": [] }, - { - "id": "8:8093454424037540087", - "lastPropertyId": "24:4272820830206771469", - "name": "FetchDownloadEntity", - "properties": [ - { - "id": "1:7366957113003324901", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "3:3174500111130052488", - "name": "bookId", - "type": 9 - }, - { - "id": "4:3949362784963767166", - "name": "title", - "type": 9 - }, - { - "id": "5:812546090900770347", - "name": "description", - "type": 9 - }, - { - "id": "6:3129463483413863468", - "name": "language", - "type": 9 - }, - { - "id": "7:3402286918039853548", - "name": "creator", - "type": 9 - }, - { - "id": "8:4732753967507809221", - "name": "publisher", - "type": 9 - }, - { - "id": "9:3239042532048399134", - "name": "date", - "type": 9 - }, - { - "id": "10:1136584919149973914", - "name": "url", - "type": 9 - }, - { - "id": "11:4252749008345744598", - "name": "articleCount", - "type": 9 - }, - { - "id": "12:8625493380854102341", - "name": "mediaCount", - "type": 9 - }, - { - "id": "13:2787210837560254021", - "name": "size", - "type": 9 - }, - { - "id": "14:2052022387195277817", - "name": "name", - "type": 9 - }, - { - "id": "15:1976493094677983679", - "name": "favIcon", - "type": 9 - }, - { - "id": "16:217454020763036675", - "name": "etaInMilliSeconds", - "type": 6 - }, - { - "id": "17:1136630637198901642", - "name": "bytesDownloaded", - "type": 6 - }, - { - "id": "18:8939019296899137627", - "name": "totalSizeOfDownload", - "type": 6 - }, - { - "id": "21:5555873126720275555", - "name": "file", - "type": 9 - }, - { - "id": "22:2724607601244650879", - "name": "downloadId", - "type": 6 - }, - { - "id": "23:5485468735259326535", - "name": "progress", - "type": 5 - }, - { - "id": "24:4272820830206771469", - "name": "tags", - "type": 9 - } - ], - "relations": [] - }, { "id": "10:3205842982118792800", "lastPropertyId": "9:5286545520416917562", @@ -416,7 +302,8 @@ "retiredEntityUids": [ 349148274283701276, 7257718270326155947, - 7394649290555378565 + 7394649290555378565, + 8093454424037540087 ], "retiredIndexUids": [ 1293695782925933448, @@ -470,7 +357,28 @@ 4335394620556092321, 1899740026144478138, 3378789699620971394, - 6867355950440828062 + 6867355950440828062, + 7366957113003324901, + 3174500111130052488, + 3949362784963767166, + 812546090900770347, + 3129463483413863468, + 3402286918039853548, + 4732753967507809221, + 3239042532048399134, + 1136584919149973914, + 4252749008345744598, + 8625493380854102341, + 2787210837560254021, + 2052022387195277817, + 1976493094677983679, + 217454020763036675, + 1136630637198901642, + 8939019296899137627, + 5555873126720275555, + 2724607601244650879, + 5485468735259326535, + 4272820830206771469 ], "retiredRelationUids": [], "version": 1 diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt index 18c45060d1..aeccd5eb10 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt @@ -20,17 +20,21 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.PrimaryKey +import androidx.room.TypeConverter +import androidx.room.TypeConverters import io.objectbox.annotation.Convert +import io.objectbox.converter.PropertyConverter import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource +import java.io.File @Entity +@TypeConverters(ZimSourceRoomConverter::class) data class HistoryRoomEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, val zimName: String, val zimFilePath: String?, - @Convert(converter = ZimSourceConverter::class, dbType = String::class) var zimReaderSource: ZimReaderSource?, val favicon: String?, var historyUrl: String, @@ -51,3 +55,13 @@ data class HistoryRoomEntity( historyItem.timeStamp ) } + +class ZimSourceRoomConverter { + @TypeConverter + fun convertToDatabaseValue(entityProperty: ZimReaderSource?) = + entityProperty?.toDatabase() ?: "" + + @TypeConverter + fun convertToEntityProperty(databaseValue: String?): ZimReaderSource = + ZimReaderSource.fromDatabaseValue(databaseValue) ?: ZimReaderSource(File("")) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index 610fb56419..5b4157477d 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -34,6 +34,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter @Suppress("UnnecessaryAbstractClass") @Database( @@ -46,7 +47,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity version = 4, exportSchema = false ) -@TypeConverters(HistoryRoomDaoCoverts::class) +@TypeConverters(HistoryRoomDaoCoverts::class, ZimSourceRoomConverter::class) abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun recentSearchRoomDao(): RecentSearchRoomDao abstract fun historyRoomDao(): HistoryRoomDao diff --git a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt index 05ed18abc6..f9209504d7 100644 --- a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt +++ b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt @@ -19,8 +19,8 @@ package org.kiwix.sharedFunctions import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity -import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status import org.kiwix.kiwixmobile.core.downloader.downloadManager.Error +import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status import org.kiwix.kiwixmobile.core.downloader.model.Base64String import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel @@ -33,6 +33,7 @@ import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity.FileElement import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity.Pieces import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity.Url +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import java.io.File @@ -41,8 +42,8 @@ import java.util.LinkedList fun bookOnDisk( databaseId: Long = 0L, book: Book = book(), - file: File = File("") -) = BookOnDisk(databaseId, book, file) + zimReaderSource: ZimReaderSource = ZimReaderSource(File("")) +) = BookOnDisk(databaseId, book, zimReaderSource) fun downloadModel( databaseId: Long = 1L, @@ -174,7 +175,7 @@ fun recentSearchEntity( fun bookOnDiskEntity( id: Long = 0, - file: File = File(""), + zimReaderSource: ZimReaderSource = ZimReaderSource(File("")), bookId: String = "", title: String = "", description: String = "", @@ -192,7 +193,7 @@ fun bookOnDiskEntity( ) = BookOnDiskEntity( id, - file, + zimReaderSource, bookId, title, description, diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt index beee136801..a39c40a662 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt @@ -33,6 +33,7 @@ import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Factory +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.files.FileSearch import org.kiwix.kiwixmobile.core.utils.files.ScanningProgressListener @@ -49,6 +50,7 @@ class StorageObserverTest { private val fileSearch: FileSearch = mockk() private val downloadModel: DownloadModel = mockk() private val file: File = mockk() + private val zimReaderSource: ZimReaderSource = mockk() private val readerFactory: Factory = mockk() private val zimFileReader: ZimFileReader = mockk() private val libkiwixBookmarks: LibkiwixBookmarks = mockk() @@ -74,7 +76,7 @@ class StorageObserverTest { every { fileSearch.scan(scanningProgressListener) } returns files every { downloadRoomDao.downloads() } returns downloads every { zimFileReader.jniKiwixReader } returns mockk() - every { runBlocking { readerFactory.create(file) } } returns zimFileReader + every { runBlocking { readerFactory.create(zimReaderSource) } } returns zimFileReader storageObserver = StorageObserver(downloadRoomDao, fileSearch, readerFactory, libkiwixBookmarks) } @@ -93,7 +95,7 @@ class StorageObserverTest { withNoFiltering() every { zimFileReader.toBook() } returns expectedBook booksOnFileSystem().assertValues( - listOf(bookOnDisk(book = expectedBook, file = file)) + listOf(bookOnDisk(book = expectedBook, zimReaderSource = zimReaderSource)) ) verify { zimFileReader.dispose() } } @@ -113,5 +115,7 @@ class StorageObserverTest { private fun withNoFiltering() { every { downloadModel.fileNameFromUrl } returns "test" every { file.absolutePath } returns "This won't match" + every { file.canonicalPath } returns "This won't match" + every { zimReaderSource.file } returns file } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/HistoryDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/HistoryDaoTest.kt index 28f7a20b95..5f6e814af7 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/HistoryDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/HistoryDaoTest.kt @@ -33,6 +33,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.HistoryEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem +import org.kiwix.kiwixmobile.core.page.historyItem import java.util.concurrent.Callable internal class HistoryDaoTest { @@ -47,7 +48,7 @@ internal class HistoryDaoTest { @Test fun deletePages() { - val historyItem: HistoryListItem.HistoryItem = mockk(relaxed = true) + val historyItem: HistoryListItem.HistoryItem = historyItem(zimReaderSource = mockk()) val historyItemList: List = listOf(historyItem) val pagesToDelete: List = historyItemList historyDao.deletePages(pagesToDelete) @@ -56,7 +57,11 @@ internal class HistoryDaoTest { @Test fun saveHistory() { - val historyItem: HistoryListItem.HistoryItem = mockk(relaxed = true) + val historyItem: HistoryListItem.HistoryItem = historyItem( + historyUrl = "", + dateString = "", + zimReaderSource = mockk() + ) val slot: CapturingSlot> = slot() every { box.store.callInTx(capture(slot)) } returns Unit val queryBuilder: QueryBuilder = mockk() @@ -74,8 +79,6 @@ internal class HistoryDaoTest { } returns queryBuilder val query: Query = mockk(relaxed = true) every { queryBuilder.build() } returns query - every { historyItem.historyUrl } returns "" - every { historyItem.dateString } returns "" historyDao.saveHistory(historyItem) slot.captured.call() verify { query.remove() } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt index dabbcf2f4a..d2f4888bcb 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt @@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_ import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import org.kiwix.sharedFunctions.book import org.kiwix.sharedFunctions.bookOnDisk @@ -75,12 +76,13 @@ internal class NewBookDaoTest { Pair { val query: Query = mockk() every { box.query().build() } returns query - val fileThatExists = mockk() - val fileThatDoesNotExist = mockk() - every { fileThatExists.exists() } returns true - every { fileThatDoesNotExist.exists() } returns false - val entityThatExists = bookOnDiskEntity(file = fileThatExists) - val entityThatDoesNotExist = bookOnDiskEntity(file = fileThatDoesNotExist) + val zimReaderSourceThatExists = mockk() + val zimReaderSourceThatDoesNotExist = mockk() + every { zimReaderSourceThatExists.exists() } returns true + every { zimReaderSourceThatDoesNotExist.exists() } returns false + val entityThatExists = bookOnDiskEntity(zimReaderSource = zimReaderSourceThatExists) + val entityThatDoesNotExist = + bookOnDiskEntity(zimReaderSource = zimReaderSourceThatDoesNotExist) mockkStatic(RxQuery::class) every { RxQuery.observable(query) } returns Observable.just( listOf(entityThatExists, entityThatDoesNotExist) @@ -110,14 +112,16 @@ internal class NewBookDaoTest { every { box.query() } returns queryBuilder every { queryBuilder.`in`( - BookOnDiskEntity_.file, - arrayOf(distinctBook.file.path), + BookOnDiskEntity_.zimReaderSource, + arrayOf(distinctBook.zimReaderSource.toDatabase()), QueryBuilder.StringOrder.CASE_INSENSITIVE ) } returns queryBuilder val query: Query = mockk(relaxed = true) every { queryBuilder.build() } returns query - every { query.find() } returns listOf(bookOnDiskEntity(file = File("matches_nothing"))) + every { + query.find() + } returns listOf(bookOnDiskEntity(zimReaderSource = ZimReaderSource(File("matches_nothing")))) slot.captured.call() verify { box.put(listOf(BookOnDiskEntity(distinctBook))) } } @@ -132,14 +136,16 @@ internal class NewBookDaoTest { every { box.query() } returns queryBuilder every { queryBuilder.`in`( - BookOnDiskEntity_.file, - arrayOf(distinctBook.file.path), + BookOnDiskEntity_.zimReaderSource, + arrayOf(distinctBook.zimReaderSource.toDatabase()), QueryBuilder.StringOrder.CASE_INSENSITIVE ) } returns queryBuilder val query: Query = mockk(relaxed = true) every { queryBuilder.build() } returns query - every { query.find() } returns listOf(bookOnDiskEntity(file = distinctBook.file)) + every { + query.find() + } returns listOf(bookOnDiskEntity(zimReaderSource = distinctBook.zimReaderSource)) slot.captured.call() verify { box.put(listOf()) } } @@ -154,8 +160,8 @@ internal class NewBookDaoTest { every { box.query() } returns queryBuilder every { queryBuilder.`in`( - BookOnDiskEntity_.file, - arrayOf(distinctBook.file.path), + BookOnDiskEntity_.zimReaderSource, + arrayOf(distinctBook.zimReaderSource.toDatabase()), QueryBuilder.StringOrder.CASE_INSENSITIVE ) } returns queryBuilder @@ -183,12 +189,23 @@ internal class NewBookDaoTest { @Test fun migrationInsert() { - val book: LibraryNetworkEntity.Book = book(file = mockk(relaxed = true)) + val book: LibraryNetworkEntity.Book = book() val slot: CapturingSlot> = slot() every { box.store.callInTx(capture(slot)) } returns Unit newBookDao.migrationInsert(listOf(book)) slot.captured.call() - verify { box.put(listOf(BookOnDiskEntity(BookOnDisk(book = book, file = book.file!!)))) } + verify { + box.put( + listOf( + BookOnDiskEntity( + BookOnDisk( + book = book, + zimReaderSource = ZimReaderSource(book.file!!) + ) + ) + ) + ) + } } @Test @@ -198,7 +215,7 @@ internal class NewBookDaoTest { every { box.query() } returns queryBuilder every { queryBuilder.endsWith( - BookOnDiskEntity_.file, + BookOnDiskEntity_.zimReaderSource, downloadTitle, QueryBuilder.StringOrder.CASE_INSENSITIVE ) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt index 4bae11d084..4b6955b0c8 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookmarksDaoTest.kt @@ -27,6 +27,7 @@ import io.objectbox.query.Query import io.objectbox.query.QueryBuilder import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_ import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity +import org.kiwix.kiwixmobile.core.page.bookmark import org.kiwix.kiwixmobile.core.page.adapter.Page import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.reader.ZimFileReader @@ -37,7 +38,7 @@ internal class NewBookmarksDaoTest { @Test fun deletePages() { - val bookmarkItem: BookmarkItem = mockk(relaxed = true) + val bookmarkItem: BookmarkItem = bookmark(zimReaderSource = mockk()) val bookmarkItemList: List = listOf(bookmarkItem) val pagesToDelete: List = bookmarkItemList newBookmarksDao.deletePages(pagesToDelete) @@ -106,7 +107,7 @@ internal class NewBookmarksDaoTest { @Test fun saveBookmark() { - val bookmarkItem: BookmarkItem = mockk(relaxed = true) + val bookmarkItem: BookmarkItem = bookmark(zimReaderSource = mockk()) newBookmarksDao.saveBookmark(bookmarkItem) verify { box.put(BookmarkEntity(bookmarkItem)) } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt index 3a68719cfc..ca62ad953d 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity_ import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.note import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import java.util.concurrent.Callable @@ -40,7 +41,7 @@ internal class NewNoteDaoTest { @Test fun deletePages() { - val notesItem: NoteListItem = mockk(relaxed = true) + val notesItem: NoteListItem = note(zimReaderSource = mockk()) val notesItemList: List = listOf(notesItem) val pagesToDelete: List = notesItemList newNotesDao.deletePages(pagesToDelete) @@ -67,7 +68,7 @@ internal class NewNoteDaoTest { @Test fun saveNotePage() { - val newNote: NoteListItem = mockk(relaxed = true) + val newNote: NoteListItem = note(title = "", zimReaderSource = mockk()) val slot: CapturingSlot> = slot() every { notesBox.store.callInTx(capture(slot)) } returns Unit val queryBuilder: QueryBuilder = mockk(relaxed = true) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt index 053bc2d27c..7c206288c6 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt @@ -19,14 +19,17 @@ package org.kiwix.kiwixmobile.core.page import org.kiwix.kiwixmobile.core.page.adapter.Page +import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkState import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState +import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.page.viewmodel.TestablePageState +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource data class PageImpl( - override val zimFilePath: String? = "zimFilePath", + override val zimReaderSource: ZimReaderSource?, override val url: String = "url", override var isSelected: Boolean = false, override val id: Long = 0L, @@ -40,15 +43,17 @@ fun historyItem( dateString: String = "5 Jul 2020", isSelected: Boolean = false, id: Long = 2, - zimId: String = "zimId" + zimId: String = "zimId", + historyUrl: String = "historyUrl", + zimReaderSource: ZimReaderSource ): HistoryListItem.HistoryItem { return HistoryListItem.HistoryItem( 2, zimId, "zimName", - "zimFilePath", + zimReaderSource, "favicon", - "historyUrl", + historyUrl, historyTitle, dateString, 100, @@ -71,22 +76,44 @@ fun historyState( ) fun bookmark( - databaseId: Long, bookmarkTitle: String = "bookmarkTitle", isSelected: Boolean = false, id: Long = 2, zimId: String = "zimId", zimName: String = "zimName", - zimFilePath: String = "zimFilePath", + zimReaderSource: ZimReaderSource, + bookmarkUrl: String = "bookmarkUrl", + favicon: String = "favicon" +): BookmarkItem { + return BookmarkItem( + id = id, + zimId = zimId, + zimName = zimName, + zimReaderSource = zimReaderSource, + bookmarkUrl = bookmarkUrl, + title = bookmarkTitle, + isSelected = isSelected, + favicon = favicon + ) +} + +fun libkiwixBookmarkItem( + databaseId: Long = 0L, + bookmarkTitle: String = "bookmarkTitle", + isSelected: Boolean = false, + id: Long = 2, + zimId: String = "zimId", + zimName: String = "zimName", + zimReaderSource: ZimReaderSource, bookmarkUrl: String = "bookmarkUrl", favicon: String = "favicon" ): LibkiwixBookmarkItem { return LibkiwixBookmarkItem( - databaseId = databaseId, id = id, zimId = zimId, zimName = zimName, - zim = zimFilePath, + zimFilePath = zimReaderSource.toDatabase(), + zimReaderSource = null, bookmarkUrl = bookmarkUrl, title = bookmarkTitle, isSelected = isSelected, @@ -95,6 +122,26 @@ fun bookmark( ) } +fun note( + zimId: String = "id", + title: String = "noteTitle", + zimUrl: String = "", + url: String = "", + noteFilePath: String = "", + zimReaderSource: ZimReaderSource, + favicon: String = "" +): NoteListItem { + return NoteListItem( + zimId = zimId, + zimUrl = zimUrl, + title = title, + url = url, + noteFilePath = noteFilePath, + zimReaderSource = zimReaderSource, + favicon = favicon + ) +} + fun bookmarkState( bookmarks: List = emptyList(), showAll: Boolean = true, diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt index 84bc750ecf..81a6e10a9c 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt @@ -18,18 +18,31 @@ package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel +import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.page.bookmark import org.kiwix.kiwixmobile.core.page.bookmarkState +import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import java.util.UUID internal class BookmarkStateTest { @Test internal fun `copyNewItems should set new items to pageItems`() { + val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE - assertThat(bookmarkState(emptyList()).copy(listOf(bookmark(databaseId))).pageItems).isEqualTo( - listOf(bookmark(databaseId)) + assertThat( + bookmarkState(emptyList()).copy( + listOf( + libkiwixBookmarkItem( + databaseId, + zimReaderSource = zimReaderSource + ) + ) + ).pageItems + ).isEqualTo( + listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource)) ) } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt index 3788a509a6..5787f7975c 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt @@ -33,14 +33,15 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.page.adapter.Page -import org.kiwix.kiwixmobile.core.page.bookmark import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects.ShowDeleteBookmarksDialog import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects.UpdateAllBookmarksPreference import org.kiwix.kiwixmobile.core.page.bookmarkState +import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.viewmodel.Action import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Filter import org.kiwix.kiwixmobile.core.page.viewmodel.Action.UpdatePages import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.sharedFunctions.InstantExecutorExtension import org.kiwix.sharedFunctions.setScheduler @@ -90,14 +91,15 @@ internal class BookmarkViewModelTest { @Test fun `updatePages return state with bookmark items`() { + val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE assertThat( viewModel.updatePages( bookmarkState(), - UpdatePages(listOf(bookmark(databaseId))) + UpdatePages(listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource))) ) ).isEqualTo( - bookmarkState(listOf(bookmark(databaseId))) + bookmarkState(listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource))) ) } @@ -122,30 +124,44 @@ internal class BookmarkViewModelTest { @Test internal fun `updatePages returns state with updated items`() { + val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE assertThat( - viewModel.updatePages(bookmarkState(), UpdatePages(listOf(bookmark(databaseId)))) + viewModel.updatePages( + bookmarkState(), + UpdatePages(listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource))) + ) ).isEqualTo( - bookmarkState(listOf(bookmark(databaseId))) + bookmarkState(listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource))) ) } @Test internal fun `deselectAllPages deselects bookmarks items`() { + val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE assertThat( viewModel.deselectAllPages( bookmarkState( bookmarks = listOf( - bookmark( + libkiwixBookmarkItem( isSelected = true, - databaseId = databaseId + databaseId = databaseId, + zimReaderSource = zimReaderSource ) ) ) ) ).isEqualTo( - bookmarkState(bookmarks = listOf(bookmark(isSelected = false, databaseId = databaseId))) + bookmarkState( + bookmarks = listOf( + libkiwixBookmarkItem( + isSelected = false, + databaseId = databaseId, + zimReaderSource = zimReaderSource + ) + ) + ) ) } @@ -165,11 +181,15 @@ internal class BookmarkViewModelTest { @Test internal fun `copyWithNewItems returns state with copied items`() { + val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE assertThat( - viewModel.copyWithNewItems(bookmarkState(), listOf(bookmark(databaseId))) + viewModel.copyWithNewItems( + bookmarkState(), + listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource)) + ) ).isEqualTo( - bookmarkState(listOf(bookmark(databaseId))) + bookmarkState(listOf(libkiwixBookmarkItem(databaseId, zimReaderSource = zimReaderSource))) ) } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt index 2c19a26cd3..cb0a8996f9 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt @@ -30,8 +30,8 @@ import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao import org.kiwix.kiwixmobile.core.main.CoreMainActivity -import org.kiwix.kiwixmobile.core.page.bookmark import org.kiwix.kiwixmobile.core.page.bookmarkState +import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteAllBookmarks @@ -71,9 +71,10 @@ internal class ShowDeleteBookmarksDialogTest { effects, bookmarkState( listOf( - bookmark( + libkiwixBookmarkItem( isSelected = true, - databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE, + zimReaderSource = mockk() ) ) ), @@ -92,8 +93,9 @@ internal class ShowDeleteBookmarksDialogTest { effects, bookmarkState( listOf( - bookmark( - databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + libkiwixBookmarkItem( + databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE, + zimReaderSource = mockk() ) ) ), diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryStateTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryStateTest.kt index d795899910..ae25b9aacb 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryStateTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryStateTest.kt @@ -18,18 +18,21 @@ package org.kiwix.kiwixmobile.core.page.history.viewmodel +import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.DateItem import org.kiwix.kiwixmobile.core.page.historyItem import org.kiwix.kiwixmobile.core.page.historyState +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource internal class HistoryStateTest { @Test internal fun `visiblePageItems returns history based on filter`() { - val matchingItem = historyItem(historyTitle = "Title") - val nonMatchingItem = historyItem(historyTitle = "noMatch") + val zimReaderSource: ZimReaderSource = mockk() + val matchingItem = historyItem(historyTitle = "Title", zimReaderSource = zimReaderSource) + val nonMatchingItem = historyItem(historyTitle = "noMatch", zimReaderSource = zimReaderSource) assertThat( historyState(listOf(matchingItem, nonMatchingItem), searchTerm = "title") .visiblePageItems @@ -38,23 +41,30 @@ internal class HistoryStateTest { @Test internal fun `copyNewItems should set new items to pageItems`() { - assertThat(historyState(emptyList()).copy(listOf(historyItem())).pageItems).isEqualTo( - listOf(historyItem()) + val zimReaderSource: ZimReaderSource = mockk() + assertThat( + historyState(emptyList()).copy( + listOf(historyItem(zimReaderSource = zimReaderSource)) + ).pageItems + ).isEqualTo( + listOf(historyItem(zimReaderSource = zimReaderSource)) ) } @Test internal fun `visiblePageItems should merge dates if on same day`() { - val item1 = historyItem() - val item2 = historyItem() + val zimReaderSource: ZimReaderSource = mockk() + val item1 = historyItem(zimReaderSource = zimReaderSource) + val item2 = historyItem(zimReaderSource = zimReaderSource) assertThat(historyState(listOf(item1, item2)).visiblePageItems) .isEqualTo(listOf(DateItem(item1.dateString), item1, item2)) } @Test internal fun `visiblePageItems should not merge dates if on different days`() { - val item1 = historyItem(dateString = "today") - val item2 = historyItem(dateString = "tomorrow") + val zimReaderSource: ZimReaderSource = mockk() + val item1 = historyItem(dateString = "today", zimReaderSource = zimReaderSource) + val item2 = historyItem(dateString = "tomorrow", zimReaderSource = zimReaderSource) assertThat(historyState(listOf(item1, item2)).visiblePageItems) .isEqualTo(listOf(DateItem(item1.dateString), item1, DateItem(item2.dateString), item2)) } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryViewModelTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryViewModelTest.kt index 90c87b7b40..247791815a 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryViewModelTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/HistoryViewModelTest.kt @@ -24,6 +24,7 @@ import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Filter import org.kiwix.kiwixmobile.core.page.viewmodel.Action.UpdatePages import org.kiwix.kiwixmobile.core.page.viewmodel.Action.UserClickedShowAllToggle import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.sharedFunctions.InstantExecutorExtension import org.kiwix.sharedFunctions.setScheduler @@ -37,6 +38,7 @@ internal class HistoryViewModelTest { private lateinit var viewModel: HistoryViewModel private val testScheduler = TestScheduler() + private val zimReaderSource: ZimReaderSource = mockk() init { setScheduler(testScheduler) @@ -72,8 +74,13 @@ internal class HistoryViewModelTest { @Test fun `updatePages return state with history items`() { - assertThat(viewModel.updatePages(historyState(), UpdatePages(listOf(historyItem())))).isEqualTo( - historyState(listOf(historyItem())) + assertThat( + viewModel.updatePages( + historyState(), + UpdatePages(listOf(historyItem(zimReaderSource = zimReaderSource))) + ) + ).isEqualTo( + historyState(listOf(historyItem(zimReaderSource = zimReaderSource))) ) } @@ -98,8 +105,28 @@ internal class HistoryViewModelTest { @Test fun `deselectAllPages returns state with all pages deselected`() { - assertThat(viewModel.deselectAllPages(historyState(listOf(historyItem(isSelected = true))))) - .isEqualTo(historyState(listOf(historyItem(isSelected = false)))) + assertThat( + viewModel.deselectAllPages( + historyState( + listOf( + historyItem( + isSelected = true, + zimReaderSource = zimReaderSource + ) + ) + ) + ) + ) + .isEqualTo( + historyState( + listOf( + historyItem( + isSelected = false, + zimReaderSource = zimReaderSource + ) + ) + ) + ) } @Test @@ -116,7 +143,21 @@ internal class HistoryViewModelTest { @Test fun `copyWithNewItems returns state with new items`() { - assertThat(viewModel.copyWithNewItems(historyState(), listOf(historyItem(isSelected = true)))) - .isEqualTo(historyState(listOf(historyItem(isSelected = true)))) + assertThat( + viewModel.copyWithNewItems( + historyState(), + listOf(historyItem(isSelected = true, zimReaderSource = zimReaderSource)) + ) + ) + .isEqualTo( + historyState( + listOf( + historyItem( + isSelected = true, + zimReaderSource = zimReaderSource + ) + ) + ) + ) } } diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/effects/ShowDeleteHistoryDialogTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/effects/ShowDeleteHistoryDialogTest.kt index f06986c569..f0403e8f49 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/effects/ShowDeleteHistoryDialogTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/history/viewmodel/effects/ShowDeleteHistoryDialogTest.kt @@ -48,7 +48,7 @@ internal class ShowDeleteHistoryDialogTest { val showDeleteHistoryDialog = ShowDeleteHistoryDialog( effects, - historyState(listOf(historyItem(isSelected = true))), + historyState(listOf(historyItem(isSelected = true, zimReaderSource = mockk()))), historyDao, viewModelScope ) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageStateTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageStateTest.kt index 591db75253..c38a0425df 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageStateTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageStateTest.kt @@ -18,6 +18,7 @@ package org.kiwix.kiwixmobile.core.page.viewmodel +import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.page.PageImpl @@ -26,19 +27,28 @@ import org.kiwix.kiwixmobile.core.page.adapter.Page internal class PageStateTest { @Test internal fun `isInSelectionMode is true when item is selected`() { - assertThat(TestablePageState(listOf(PageImpl(isSelected = true))).isInSelectionState) + assertThat( + TestablePageState( + listOf( + PageImpl( + isSelected = true, + zimReaderSource = mockk() + ) + ) + ).isInSelectionState + ) .isEqualTo(true) } @Test internal fun `isInSelectionMode is false when no item is selected`() { - assertThat(TestablePageState(listOf(PageImpl())).isInSelectionState) + assertThat(TestablePageState(listOf(PageImpl(zimReaderSource = mockk()))).isInSelectionState) .isEqualTo(false) } @Test internal fun `filteredPageItems should show all if show all is true`() { - val item = PageImpl(zimId = "notSame") + val item = PageImpl(zimId = "notSame", zimReaderSource = mockk()) assertThat( TestablePageState( listOf(item), @@ -49,7 +59,7 @@ internal class PageStateTest { @Test internal fun `filteredPageItems should not show all if showAll is false with different zimId`() { - val item = PageImpl(zimId = "notSame") + val item = PageImpl(zimId = "notSame", zimReaderSource = mockk()) assertThat( TestablePageState(listOf(item), showAll = false).publicFilteredPageItems ).isEqualTo(emptyList()) @@ -57,7 +67,7 @@ internal class PageStateTest { @Test internal fun `filteredPageItems should show item if zimId is same`() { - val item = PageImpl(zimId = "sameId") + val item = PageImpl(zimId = "sameId", zimReaderSource = mockk()) assertThat( TestablePageState( listOf(item), @@ -69,7 +79,7 @@ internal class PageStateTest { @Test internal fun `filteredPageItems should hide items with not equal searchTerm`() { - val item = PageImpl(title = "title") + val item = PageImpl(title = "title", zimReaderSource = mockk()) assertThat( TestablePageState( listOf(item), @@ -81,7 +91,7 @@ internal class PageStateTest { @Test internal fun `filteredPageItems should show items with equal searchTerm (ignore case)`() { - val item = PageImpl(title = "title") + val item = PageImpl(title = "title", zimReaderSource = mockk()) assertThat( TestablePageState( listOf(item), diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelTest.kt index 7795495e9b..4421df77bc 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/PageViewModelTest.kt @@ -45,6 +45,7 @@ import org.kiwix.kiwixmobile.core.page.viewmodel.Action.UserClickedDeleteSelecte import org.kiwix.kiwixmobile.core.page.viewmodel.Action.UserClickedShowAllToggle import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenPage import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.search.viewmodel.effects.PopFragmentBackstack import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.sharedFunctions.InstantExecutorExtension @@ -116,26 +117,43 @@ internal class PageViewModelTest { @Test internal fun `OnItemClick selects item if one is selected`() { - val page = PageImpl(isSelected = true) + val zimReaderSource: ZimReaderSource = mockk() + val page = PageImpl(isSelected = true, zimReaderSource = zimReaderSource) viewModel.state.postValue(TestablePageState(listOf(page))) viewModel.actions.offer(OnItemClick(page)) - viewModel.state.test().assertValue(TestablePageState(listOf(PageImpl()))) + viewModel.state.test() + .assertValue(TestablePageState(listOf(PageImpl(zimReaderSource = zimReaderSource)))) } @Test internal fun `OnItemClick offers OpenPage if none is selected`() { - viewModel.state.postValue(TestablePageState(listOf(PageImpl()))) - viewModel.effects.test().also { viewModel.actions.offer(OnItemClick(PageImpl())) } - .assertValue(OpenPage(PageImpl(), zimReaderContainer)) - viewModel.state.test().assertValue(TestablePageState(listOf(PageImpl()))) + val zimReaderSource: ZimReaderSource = mockk() + viewModel.state.postValue( + TestablePageState(listOf(PageImpl(zimReaderSource = zimReaderSource))) + ) + viewModel.effects.test() + .also { viewModel.actions.offer(OnItemClick(PageImpl(zimReaderSource = zimReaderSource))) } + .assertValue(OpenPage(PageImpl(zimReaderSource = zimReaderSource), zimReaderContainer)) + viewModel.state.test() + .assertValue(TestablePageState(listOf(PageImpl(zimReaderSource = zimReaderSource)))) } @Test internal fun `OnItemLongClick selects item if none is selected`() { - val page = PageImpl() + val zimReaderSource: ZimReaderSource = mockk() + val page = PageImpl(zimReaderSource = zimReaderSource) viewModel.state.postValue(TestablePageState(listOf(page))) viewModel.actions.offer(OnItemLongClick(page)) - viewModel.state.test().assertValue(TestablePageState(listOf(PageImpl(isSelected = true)))) + viewModel.state.test().assertValue( + TestablePageState( + listOf( + PageImpl( + isSelected = true, + zimReaderSource = zimReaderSource + ) + ) + ) + ) } @Test diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/DeletePageItemsTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/DeletePageItemsTest.kt index 4f308187a8..f9c42927a9 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/DeletePageItemsTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/DeletePageItemsTest.kt @@ -28,12 +28,14 @@ import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.dao.PageDao import org.kiwix.kiwixmobile.core.page.historyItem import org.kiwix.kiwixmobile.core.page.historyState +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource internal class DeletePageItemsTest { private val pageDao: PageDao = mockk(relaxed = true) val activity: AppCompatActivity = mockk() - private val item1 = historyItem() - private val item2 = historyItem() + private val zimReaderSource: ZimReaderSource = mockk() + private val item1 = historyItem(zimReaderSource = zimReaderSource) + private val item2 = historyItem(zimReaderSource = zimReaderSource) private val viewModelScope = CoroutineScope(Dispatchers.Main) @Test diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPageTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPageTest.kt index 2e6971a6b5..b31154de72 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPageTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/viewmodel/effects/OpenPageTest.kt @@ -26,9 +26,11 @@ import org.junit.jupiter.api.Test import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.page.PageImpl import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource internal class OpenPageTest { - private val page = PageImpl() + private val zimReaderSource: ZimReaderSource = mockk() + private val page = PageImpl(zimReaderSource = zimReaderSource) private val zimReaderContainer: ZimReaderContainer = mockk() val activity: CoreMainActivity = mockk() @@ -39,7 +41,7 @@ internal class OpenPageTest { @Test fun `invokeWith navigates to page with historyUrl`() { - every { zimReaderContainer.zimCanonicalPath } returns "zimFilePath" + every { zimReaderContainer.zimReaderSource } returns zimReaderSource OpenPage(page, zimReaderContainer).invokeWith(activity) verify { activity.openPage(page.url) @@ -48,10 +50,10 @@ internal class OpenPageTest { @Test fun `invokeWith navigates to page with historyUrl and zimFilePath`() { - every { zimReaderContainer.zimCanonicalPath } returns "notZimFilePath" + every { zimReaderContainer.zimReaderSource } returns null OpenPage(page, zimReaderContainer).invokeWith(activity) verify { - activity.openPage(page.url, page.zimFilePath!!) + activity.openPage(page.url, page.zimReaderSource!!) } } } diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 8052db1883..1926899bfd 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -36,6 +36,7 @@ import org.kiwix.kiwixmobile.core.extensions.getResizedDrawable import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.main.CoreReaderFragment import org.kiwix.kiwixmobile.core.main.MainMenu +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getDemoFilePathForCustomApp @@ -182,25 +183,28 @@ class CustomReaderFragment : CoreReaderFragment() { onFilesFound = { when (it) { is ValidationState.HasFile -> { - if (it.assetFileDescriptorList.isNotEmpty()) { - openZimFile(null, true, it.assetFileDescriptorList) - } else { - openZimFile(it.file, true) - } + openZimFile( + ZimReaderSource( + file = it.file, + null, + it.assetFileDescriptorList + ), + true + ) // Save book in the database to display it in `ZimHostFragment`. zimReaderContainer?.zimFileReader?.let { zimFileReader -> // Check if the file is not null. If the file is null, // it means we have created zimFileReader with a fileDescriptor, // so we create a demo file to save it in the database for display on the `ZimHostFragment`. val file = it.file ?: createDemoFile() - val bookOnDisk = BookOnDisk(file, zimFileReader) + val bookOnDisk = BookOnDisk(zimFileReader) repositoryActions?.saveBook(bookOnDisk) } } is ValidationState.HasBothFiles -> { it.zimFile.delete() - openZimFile(it.obbFile, true) + openZimFile(ZimReaderSource(it.obbFile), true) } else -> {} From 58cbd5dbbeb7a05ba834e6a7638c6be9a91afaa8 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 17:21:13 +0530 Subject: [PATCH 06/19] Fixed some compliation errors --- .../src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt | 3 ++- .../org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt | 2 +- .../org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index 721a58b389..9439f86e6e 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -55,7 +55,8 @@ class NewBookDao @Inject constructor(private val box: Box) { private fun booksWithSameFilePath(booksOnDisk: List) = box.query { inValues( - BookOnDiskEntity_.file, booksOnDisk.map { it.zimReaderSource.toDatabase() }.toTypedArray(), + BookOnDiskEntity_.zimReaderSource, + booksOnDisk.map { it.zimReaderSource.toDatabase() }.toTypedArray(), QueryBuilder.StringOrder.CASE_INSENSITIVE ) }.find() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt index 3ae3e95271..de00a5d291 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryEntity.kt @@ -30,7 +30,7 @@ data class HistoryEntity( val zimName: String, val zimFilePath: String?, // keep this to handle previously saved history @Convert(converter = ZimSourceConverter::class, dbType = String::class) - var zimReaderSource: ZimReaderSource, + var zimReaderSource: ZimReaderSource?, val favicon: String?, val historyUrl: String, val historyTitle: String, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt index 5c4cae24a3..3d3f81e7d5 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesEntity.kt @@ -30,7 +30,7 @@ data class NotesEntity( val zimId: String, var zimFilePath: String?, // keep this to handle previously saved notes @Convert(converter = ZimSourceConverter::class, dbType = String::class) - var zimReaderSource: ZimReaderSource, + var zimReaderSource: ZimReaderSource?, val zimUrl: String, var noteTitle: String, var noteFilePath: String, From 31991bdf1af9fc7cf627de8b990bec302ee42439 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 17:39:16 +0530 Subject: [PATCH 07/19] Fixed adding books to library while importing the bookmarks. Also improved the convertor of room and objectbox --- .../org/kiwix/kiwixmobile/core/dao/LibkiwixBookmarks.kt | 2 +- .../kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt | 2 +- .../kiwixmobile/core/dao/entities/HistoryRoomEntity.kt | 6 +----- .../kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt | 2 -- 4 files changed, 3 insertions(+), 9 deletions(-) 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 cebfb30ac3..bd909712ff 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 @@ -417,7 +417,7 @@ class LibkiwixBookmarks @Inject constructor( } // Add the ZIM files to the library for validating the bookmarks. bookDao.getBooks().forEach { - addBookToLibrary(file = it.file) + addBookToLibrary(file = it.zimReaderSource.file) } // Save the imported bookmarks to the current library. tempLibrary.getBookmarks(false)?.toList()?.forEach { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt index c8fa41f555..2cd30af1b6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt @@ -86,7 +86,7 @@ data class BookOnDiskEntity( } class ZimSourceConverter : PropertyConverter { - override fun convertToDatabaseValue(entityProperty: ZimReaderSource?) = + override fun convertToDatabaseValue(entityProperty: ZimReaderSource?): String = entityProperty?.toDatabase() ?: "" override fun convertToEntityProperty(databaseValue: String?): ZimReaderSource = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt index aeccd5eb10..0a26d136e7 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt @@ -21,15 +21,11 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.PrimaryKey import androidx.room.TypeConverter -import androidx.room.TypeConverters -import io.objectbox.annotation.Convert -import io.objectbox.converter.PropertyConverter import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import java.io.File @Entity -@TypeConverters(ZimSourceRoomConverter::class) data class HistoryRoomEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, @@ -58,7 +54,7 @@ data class HistoryRoomEntity( class ZimSourceRoomConverter { @TypeConverter - fun convertToDatabaseValue(entityProperty: ZimReaderSource?) = + fun convertToDatabaseValue(entityProperty: ZimReaderSource?): String = entityProperty?.toDatabase() ?: "" @TypeConverter diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt index 5bc7c07d4e..ed3e0a772e 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt @@ -21,7 +21,6 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey -import io.objectbox.annotation.Convert import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @@ -31,7 +30,6 @@ data class NotesRoomEntity( var id: Long = 0L, val zimId: String, var zimFilePath: String?, // keep this to handle previously saved notes - @Convert(converter = ZimSourceConverter::class, dbType = String::class) var zimReaderSource: ZimReaderSource?, val zimUrl: String, var noteTitle: String, From b667553a8f8f4cfd630172c4e84a27f551c48c8d Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 18:58:52 +0530 Subject: [PATCH 08/19] Fixed Migration is not properly running for HistoryRoomEntity --- .../core/dao/entities/HistoryRoomEntity.kt | 3 + .../core/dao/entities/NotesRoomEntity.kt | 2 + .../core/data/KiwixRoomDatabase.kt | 64 ++++++++++++++++++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt index 0a26d136e7..0297654696 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt @@ -18,9 +18,11 @@ package org.kiwix.kiwixmobile.core.dao.entities +import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import androidx.room.TypeConverter +import androidx.room.TypeConverters import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import java.io.File @@ -31,6 +33,7 @@ data class HistoryRoomEntity( val zimId: String, val zimName: String, val zimFilePath: String?, + @TypeConverters(ZimSourceRoomConverter::class) var zimReaderSource: ZimReaderSource?, val favicon: String?, var historyUrl: String, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt index ed3e0a772e..9a2b0c01b3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/NotesRoomEntity.kt @@ -21,6 +21,7 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey +import androidx.room.TypeConverters import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource @@ -30,6 +31,7 @@ data class NotesRoomEntity( var id: Long = 0L, val zimId: String, var zimFilePath: String?, // keep this to handle previously saved notes + @TypeConverters(ZimSourceRoomConverter::class) var zimReaderSource: ZimReaderSource?, val zimUrl: String, var noteTitle: String, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index 5b4157477d..d6ff581192 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -44,7 +44,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter NotesRoomEntity::class, DownloadRoomEntity::class ], - version = 4, + version = 5, exportSchema = false ) @TypeConverters(HistoryRoomDaoCoverts::class, ZimSourceRoomConverter::class) @@ -62,8 +62,8 @@ abstract class KiwixRoomDatabase : RoomDatabase() { ?: Room.databaseBuilder(context, KiwixRoomDatabase::class.java, "KiwixRoom.db") // We have already database name called kiwix.db in order to avoid complexity we named // as kiwixRoom.db - .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) - .build() + .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5) + .build().also { db = it } } } @@ -148,6 +148,64 @@ abstract class KiwixRoomDatabase : RoomDatabase() { } } + @Suppress("MagicNumber") + private val MIGRATION_4_5 = object : Migration(4, 5) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE HistoryRoomEntity ADD COLUMN zimReaderSource TEXT") + database.execSQL( + """ + CREATE TABLE IF NOT EXISTS HistoryRoomEntity_temp ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + zimId TEXT NOT NULL, + zimName TEXT NOT NULL, + zimFilePath TEXT, + favicon TEXT, + historyUrl TEXT NOT NULL, + historyTitle TEXT NOT NULL, + dateString TEXT NOT NULL, + timeStamp INTEGER NOT NULL, + zimReaderSource TEXT + ) + """ + ) + database.execSQL( + """ + INSERT INTO HistoryRoomEntity_temp ( + id, + zimId, + zimName, + zimFilePath, + favicon, + historyUrl, + historyTitle, + dateString, + timeStamp, + zimReaderSource + ) + SELECT + id, + zimId, + zimName, + zimFilePath, + favicon, + historyUrl, + historyTitle, + dateString, + timeStamp, + zimReaderSource + FROM HistoryRoomEntity + """ + ) + + // Step 3: Drop the old table + database.execSQL("DROP TABLE HistoryRoomEntity") + + // Step 4: Rename the new table to the old table's name + database.execSQL("ALTER TABLE HistoryRoomEntity_temp RENAME TO HistoryRoomEntity") + database.execSQL("ALTER TABLE NotesRoomEntity ADD COLUMN zimReaderSource TEXT") + } + } + fun destroyInstance() { db = null } From 3ffe4cc6a7c0c5b4baecc0f615d765bec6371ff2 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 19:18:29 +0530 Subject: [PATCH 09/19] Fixed instrumentation test case compilation errors --- .../kiwix/kiwixmobile/KiwixRoomDatabaseTest.kt | 18 ++++++++++++------ .../kiwixmobile/ObjectBoxToRoomMigratorTest.kt | 4 ++-- .../ZimFileReaderWithSplittedZimFileTest.kt | 11 +++++------ .../kiwixmobile/roomDao/HistoryRoomDaoTest.kt | 2 +- .../kiwixmobile/roomDao/NoteRoomDaoTest.kt | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/KiwixRoomDatabaseTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/KiwixRoomDatabaseTest.kt index 2e969726b1..3eb6052723 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/KiwixRoomDatabaseTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/KiwixRoomDatabaseTest.kt @@ -38,6 +38,8 @@ import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity import org.kiwix.kiwixmobile.core.data.KiwixRoomDatabase import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource +import java.io.File @RunWith(AndroidJUnit4::class) class KiwixRoomDatabaseTest { @@ -112,7 +114,7 @@ class KiwixRoomDatabaseTest { assertThat(zimId, equalTo(historyItem.zimId)) assertThat(zimName, equalTo(historyItem.zimName)) assertThat(historyUrl, equalTo(historyItem.historyUrl)) - assertThat(zimFilePath, equalTo(historyItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(historyItem.zimReaderSource)) assertThat(favicon, equalTo(historyItem.favicon)) assertThat(dateString, equalTo(historyItem.dateString)) assertThat(timeStamp, equalTo(historyItem.timeStamp)) @@ -152,7 +154,7 @@ class KiwixRoomDatabaseTest { assertThat(zimId, equalTo(noteItem.zimId)) assertThat(zimUrl, equalTo(noteItem.zimUrl)) assertThat(title, equalTo(noteItem.title)) - assertThat(zimFilePath, equalTo(noteItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(noteItem.zimReaderSource)) assertThat(noteFilePath, equalTo(noteItem.noteFilePath)) assertThat(favicon, equalTo(noteItem.favicon)) } @@ -186,7 +188,9 @@ class KiwixRoomDatabaseTest { databaseId: Long = 0L, zimId: String = "1f88ab6f-c265-b-3ff-8f49-b7f4429503800", zimName: String = "alpinelinux_en_all", - zimFilePath: String = "/storage/emulated/0/Download/alpinelinux_en_all_maxi_2023-01.zim", + zimReaderSource: ZimReaderSource = ZimReaderSource( + File("/storage/emulated/0/Download/alpinelinux_en_all_maxi_2023-01.zim") + ), timeStamp: Long = System.currentTimeMillis() ): HistoryListItem.HistoryItem = HistoryListItem.HistoryItem( @@ -195,7 +199,7 @@ class KiwixRoomDatabaseTest { zimName = zimName, historyUrl = historyUrl, title = title, - zimFilePath = zimFilePath, + zimReaderSource = zimReaderSource, favicon = null, dateString = dateString, timeStamp = timeStamp @@ -205,14 +209,16 @@ class KiwixRoomDatabaseTest { databaseId: Long = 0L, zimId: String = "1f88ab6f-c265-b-3ff-8f49-b7f4429503800", title: String = "Alpine Wiki", - zimFilePath: String = "/storage/emulated/0/Download/alpinelinux_en_all_maxi_2023-01.zim", + zimReaderSource: ZimReaderSource = ZimReaderSource( + File("/storage/emulated/0/Download/alpinelinux_en_all_maxi_2023-01.zim") + ), zimUrl: String, noteFilePath: String = "/storage/emulated/0/Download/Notes/Alpine linux/AlpineNote.txt" ): NoteListItem = NoteListItem( databaseId = databaseId, zimId = zimId, title = title, - zimFilePath = zimFilePath, + zimReaderSource = zimReaderSource, zimUrl = zimUrl, noteFilePath = noteFilePath, null, diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToRoomMigratorTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToRoomMigratorTest.kt index 841e00d851..98eab2566e 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToRoomMigratorTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/ObjectBoxToRoomMigratorTest.kt @@ -201,7 +201,7 @@ class ObjectBoxToRoomMigratorTest { assertThat(zimId, equalTo(historyItem.zimId)) assertThat(zimName, equalTo(historyItem.zimName)) assertThat(historyUrl, equalTo(historyItem.historyUrl)) - assertThat(zimFilePath, equalTo(historyItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(historyItem.zimReaderSource)) assertThat(favicon, equalTo(historyItem.favicon)) assertThat(dateString, equalTo(historyItem.dateString)) assertThat(timeStamp, equalTo(historyItem.timeStamp)) @@ -325,7 +325,7 @@ class ObjectBoxToRoomMigratorTest { assertThat(zimId, equalTo(noteItem.zimId)) assertThat(zimUrl, equalTo(noteItem.zimUrl)) assertThat(title, equalTo(noteItem.title)) - assertThat(zimFilePath, equalTo(noteItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(noteItem.zimReaderSource)) assertThat(noteFilePath, equalTo(noteItem.noteFilePath)) assertThat(favicon, equalTo(noteItem.favicon)) } diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/ZimFileReaderWithSplittedZimFileTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/ZimFileReaderWithSplittedZimFileTest.kt index 7c04551b88..cfb168dd0e 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/ZimFileReaderWithSplittedZimFileTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/reader/ZimFileReaderWithSplittedZimFileTest.kt @@ -37,6 +37,7 @@ import org.kiwix.kiwixmobile.BaseActivityTest import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.reader.ZimFileReader +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.main.KiwixMainActivity @@ -44,7 +45,6 @@ import org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragmentDirecti import org.kiwix.kiwixmobile.page.history.navigationHistory import org.kiwix.kiwixmobile.testutils.RetryRule import org.kiwix.kiwixmobile.testutils.TestUtils -import org.kiwix.libzim.Archive import org.kiwix.libzim.SuggestionSearcher import java.io.File import java.io.FileOutputStream @@ -118,12 +118,11 @@ class ZimFileReaderWithSplittedZimFileTest : BaseActivityTest() { fun testWithExtraZeroSizeFile() { createAndGetSplitedZimFile(true)?.let { zimFile -> // test the articleCount and mediaCount of this zim file. - val archive = Archive(zimFile.canonicalPath) + val zimReaderSource = ZimReaderSource(zimFile) + val archive = zimReaderSource.createArchive() val zimFileReader = ZimFileReader( - zimFile, - emptyList(), - null, - archive, + zimReaderSource, + archive!!, DarkModeConfig(SharedPreferenceUtil(context), context), SuggestionSearcher(archive) ) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/HistoryRoomDaoTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/HistoryRoomDaoTest.kt index 0775fc4a29..a714d0213a 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/HistoryRoomDaoTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/HistoryRoomDaoTest.kt @@ -70,7 +70,7 @@ class HistoryRoomDaoTest { assertThat(zimId, equalTo(historyItem.zimId)) assertThat(zimName, equalTo(historyItem.zimName)) assertThat(historyUrl, equalTo(historyItem.historyUrl)) - assertThat(zimFilePath, equalTo(historyItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(historyItem.zimReaderSource)) assertThat(favicon, equalTo(historyItem.favicon)) assertThat(dateString, equalTo(historyItem.dateString)) assertThat(timeStamp, equalTo(historyItem.timeStamp)) diff --git a/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/NoteRoomDaoTest.kt b/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/NoteRoomDaoTest.kt index 8dbcf4dc94..9bb3496d5d 100644 --- a/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/NoteRoomDaoTest.kt +++ b/app/src/androidTest/java/org/kiwix/kiwixmobile/roomDao/NoteRoomDaoTest.kt @@ -68,7 +68,7 @@ class NoteRoomDaoTest { assertThat(zimId, equalTo(noteItem.zimId)) assertThat(zimUrl, equalTo(noteItem.zimUrl)) assertThat(title, equalTo(noteItem.title)) - assertThat(zimFilePath, equalTo(noteItem.zimFilePath)) + assertThat(zimReaderSource, equalTo(noteItem.zimReaderSource)) assertThat(noteFilePath, equalTo(noteItem.noteFilePath)) assertThat(favicon, equalTo(noteItem.favicon)) } From dbead86c57988111a734d00534bc3a2c5eecdce5 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 19:21:28 +0530 Subject: [PATCH 10/19] Fixed SearchFragmentTestForCustomApp test case --- .../custom/search/SearchFragmentTestForCustomApp.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt index 9afff2746a..80a00d2736 100644 --- a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt +++ b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt @@ -42,6 +42,7 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.search.SearchFragment import org.kiwix.kiwixmobile.core.search.viewmodel.Action import org.kiwix.kiwixmobile.core.utils.LanguageUtils @@ -266,7 +267,10 @@ class SearchFragmentTestForCustomApp { ) as NavHostFragment val customReaderFragment = navHostFragment.childFragmentManager.fragments[0] as CustomReaderFragment - customReaderFragment.openZimFile(null, true, listOf(assetFileDescriptor)) + customReaderFragment.openZimFile( + ZimReaderSource(null, null, listOf(assetFileDescriptor)), + true + ) } } From ac36538e1da8bc054386976f9cdf168f38274ec2 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 19:23:18 +0530 Subject: [PATCH 11/19] Fixed static analysis failure --- .../org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt index 0297654696..8335ba2a8b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/HistoryRoomEntity.kt @@ -18,7 +18,6 @@ package org.kiwix.kiwixmobile.core.dao.entities -import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import androidx.room.TypeConverter From 3d976d93048d461e76559d4556ad14608c16fa0d Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 24 Aug 2024 19:44:49 +0530 Subject: [PATCH 12/19] Fixed all unit coverage failures. --- .../org/kiwix/kiwixmobile/core/StorageObserverTest.kt | 1 + .../org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt | 1 - .../org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt | 1 + .../core/page/bookmark/viewmodel/BookmarkStateTest.kt | 2 ++ .../page/bookmark/viewmodel/BookmarkViewModelTest.kt | 4 ++++ .../viewmodel/effects/ShowDeleteBookmarksDialogTest.kt | 9 +++++++-- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt index a39c40a662..80cd08221a 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/StorageObserverTest.kt @@ -94,6 +94,7 @@ class StorageObserverTest { ) withNoFiltering() every { zimFileReader.toBook() } returns expectedBook + every { zimFileReader.zimReaderSource } returns zimReaderSource booksOnFileSystem().assertValues( listOf(bookOnDisk(book = expectedBook, zimReaderSource = zimReaderSource)) ) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt index ca62ad953d..b924480601 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewNoteDaoTest.kt @@ -75,7 +75,6 @@ internal class NewNoteDaoTest { every { notesBox.query() } returns queryBuilder val query: Query = mockk(relaxed = true) every { queryBuilder.build() } returns query - every { newNote.title } returns "" every { queryBuilder.equal( NotesEntity_.noteTitle, diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt index 7c206288c6..b3b8eab374 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/PageTestHelpers.kt @@ -109,6 +109,7 @@ fun libkiwixBookmarkItem( favicon: String = "favicon" ): LibkiwixBookmarkItem { return LibkiwixBookmarkItem( + databaseId = databaseId, id = id, zimId = zimId, zimName = zimName, diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt index 81a6e10a9c..c16f25fa92 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkStateTest.kt @@ -18,6 +18,7 @@ package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel +import io.mockk.every import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -32,6 +33,7 @@ internal class BookmarkStateTest { internal fun `copyNewItems should set new items to pageItems`() { val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + every { zimReaderSource.toDatabase() } returns "" assertThat( bookmarkState(emptyList()).copy( listOf( diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt index 5787f7975c..08b63ae06c 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/BookmarkViewModelTest.kt @@ -93,6 +93,7 @@ internal class BookmarkViewModelTest { fun `updatePages return state with bookmark items`() { val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + every { zimReaderSource.toDatabase() } returns "" assertThat( viewModel.updatePages( bookmarkState(), @@ -126,6 +127,7 @@ internal class BookmarkViewModelTest { internal fun `updatePages returns state with updated items`() { val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + every { zimReaderSource.toDatabase() } returns "" assertThat( viewModel.updatePages( bookmarkState(), @@ -140,6 +142,7 @@ internal class BookmarkViewModelTest { internal fun `deselectAllPages deselects bookmarks items`() { val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + every { zimReaderSource.toDatabase() } returns "" assertThat( viewModel.deselectAllPages( bookmarkState( @@ -183,6 +186,7 @@ internal class BookmarkViewModelTest { internal fun `copyWithNewItems returns state with copied items`() { val zimReaderSource: ZimReaderSource = mockk() val databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE + every { zimReaderSource.toDatabase() } returns "" assertThat( viewModel.copyWithNewItems( bookmarkState(), diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt index cb0a8996f9..584ceac81f 100644 --- a/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/page/bookmark/viewmodel/effects/ShowDeleteBookmarksDialogTest.kt @@ -33,6 +33,7 @@ import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.page.bookmarkState import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems +import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteAllBookmarks import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteSelectedBookmarks @@ -66,6 +67,8 @@ internal class ShowDeleteBookmarksDialogTest { @Test fun `invoke with selected items shows dialog with DeleteSelectedBookmarks title`() = runBlocking { + val zimReaderSource: ZimReaderSource = mockk() + every { zimReaderSource.toDatabase() } returns "" val showDeleteBookmarksDialog = ShowDeleteBookmarksDialog( effects, @@ -74,7 +77,7 @@ internal class ShowDeleteBookmarksDialogTest { libkiwixBookmarkItem( isSelected = true, databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE, - zimReaderSource = mockk() + zimReaderSource = zimReaderSource ) ) ), @@ -88,6 +91,8 @@ internal class ShowDeleteBookmarksDialogTest { @Test fun `invoke with no selected items shows dialog with DeleteAllBookmarks title`() = runBlocking { + val zimReaderSource: ZimReaderSource = mockk() + every { zimReaderSource.toDatabase() } returns "" val showDeleteBookmarksDialog = ShowDeleteBookmarksDialog( effects, @@ -95,7 +100,7 @@ internal class ShowDeleteBookmarksDialogTest { listOf( libkiwixBookmarkItem( databaseId = UUID.randomUUID().mostSignificantBits and Long.MAX_VALUE, - zimReaderSource = mockk() + zimReaderSource = zimReaderSource ) ) ), From 769aaeea3d595b07eb210adb3c00bd3f656420c7 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 13:07:29 +0530 Subject: [PATCH 13/19] Fixed ObjectBoxToLibkiwixMigratorTest was failing. --- .../core/page/bookmark/adapter/LibkiwixBookmarkItem.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt index 6a818ac6f8..efe2835fc6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/bookmark/adapter/LibkiwixBookmarkItem.kt @@ -48,7 +48,7 @@ data class LibkiwixBookmarkItem( zimId = libkiwixBookmark.bookId, zimName = libkiwixBookmark.bookTitle, zimFilePath = zimReaderSource?.toDatabase(), - zimReaderSource = null, + zimReaderSource = zimReaderSource, bookmarkUrl = libkiwixBookmark.url, title = libkiwixBookmark.title, favicon = favicon, @@ -62,7 +62,7 @@ data class LibkiwixBookmarkItem( libKiwixBook: Book ) : this( zimFilePath = zimFileReader.zimReaderSource.toDatabase(), - zimReaderSource = null, + zimReaderSource = zimFileReader.zimReaderSource, zimId = libKiwixBook.id, zimName = libKiwixBook.name, bookmarkUrl = articleUrl, @@ -77,7 +77,7 @@ data class LibkiwixBookmarkItem( ) : this( zimId = bookmarkEntity.zimId, zimFilePath = bookmarkEntity.zimReaderSource?.toDatabase(), - zimReaderSource = null, + zimReaderSource = bookmarkEntity.zimReaderSource, zimName = bookmarkEntity.zimName, bookmarkUrl = bookmarkEntity.bookmarkUrl, title = bookmarkEntity.bookmarkTitle, From 5e8abe11532d06c02387637a82d4a64e78805b2e Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 13:21:39 +0530 Subject: [PATCH 14/19] Fixed zim file is not showing when we open it from the notes screen. --- .../core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt index 47d65b9df5..cb8990da66 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/notes/viewmodel/effects/ShowOpenNoteDialog.kt @@ -56,10 +56,10 @@ data class ShowOpenNoteDialog( // For custom apps, we are currently using fileDescriptor, and they only have a single file in them, // which is already set in zimReaderContainer, so there's no need to set it again. item.zimReaderSource?.toDatabase().let { + val currentZimReaderSource = zimReaderContainer.zimReaderSource if (!activity.isCustomApp()) { zimReaderContainer.setZimReaderSource(item.zimReaderSource) } - val currentZimReaderSource = zimReaderContainer.zimReaderSource if (zimReaderContainer.zimReaderSource != currentZimReaderSource) { // if current zim file is not the same set the main page of that zim file // so that when we go back it properly loads the article, and do nothing if the From 561ff4090c612871931155dea4c4b6fc5f70cc8d Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 13:42:22 +0530 Subject: [PATCH 15/19] Fixed: Zim File was not opening if we opened it through the DeepLinking. --- .../destination/reader/KiwixReaderFragment.kt | 19 ++++++++++--------- .../core/main/CoreReaderFragment.kt | 4 ++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index 5642d07318..c5b73ca187 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -33,7 +33,9 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.net.toFile import androidx.drawerlayout.widget.DrawerLayout +import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomnavigation.BottomNavigationView +import kotlinx.coroutines.launch import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.cachedComponent import org.kiwix.kiwixmobile.core.R.anim @@ -325,18 +327,17 @@ class KiwixReaderFragment : CoreReaderFragment() { private fun openAndSaveZimFileInLocalLibrary(file: File) { val zimReaderSource = ZimReaderSource(file) if (zimReaderSource.canOpenInLibkiwix()) { - zimReaderContainer?.let { zimReaderContainer -> - zimReaderContainer.setZimReaderSource(zimReaderSource) - - zimReaderContainer.zimFileReader?.let { zimFileReader -> - BooksOnDiskListItem.BookOnDisk(zimFileReader).also { bookOnDisk -> - // save the book in the library - repositoryActions?.saveBook(bookOnDisk) - zimFileReader.dispose() + openZimFile(zimReaderSource).also { + lifecycleScope.launch { + zimReaderFactory?.create(zimReaderSource)?.let { zimFileReader -> + BooksOnDiskListItem.BookOnDisk(zimFileReader).also { bookOnDisk -> + // save the book in the library + repositoryActions?.saveBook(bookOnDisk) + zimFileReader.dispose() + } } } } - openZimFile(ZimReaderSource(file)) } else { activity.toast(R.string.cannot_open_file) } 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 2916d03eb6..e95d01394d 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 @@ -207,6 +207,10 @@ abstract class CoreReaderFragment : @Inject var zimReaderContainer: ZimReaderContainer? = null + @JvmField + @Inject + var zimReaderFactory: ZimFileReader.Factory? = null + @JvmField @Inject var darkModeConfig: DarkModeConfig? = null From a86de10c199a232ca08a0e0b27e35197b1164f82 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 15:07:11 +0530 Subject: [PATCH 16/19] Improved the saving of the zim file in the local library when we open the zim file via deep linking or via file picker. We have moved this functionality to the background thread so that it will not block the UI thread and provide a smooth user experience. --- .../nav/destination/library/LocalLibraryFragment.kt | 8 +++++--- .../nav/destination/reader/KiwixReaderFragment.kt | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt index 6fe6c1f9e8..069f4a450f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt @@ -56,10 +56,12 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.bottomnavigation.BottomNavigationView import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.kiwix.kiwixmobile.R -import org.kiwix.kiwixmobile.core.R.string import org.kiwix.kiwixmobile.cachedComponent +import org.kiwix.kiwixmobile.core.R.string import org.kiwix.kiwixmobile.core.base.BaseActivity import org.kiwix.kiwixmobile.core.base.BaseFragment import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isManageExternalStoragePermissionGranted @@ -405,7 +407,7 @@ class LocalLibraryFragment : BaseFragment() { // local library screen. Since our application is already aware of this opened ZIM file, // we can directly add it to the database. // See https://github.com/kiwix/kiwix-android/issues/3650 - runBlocking { + CoroutineScope(Dispatchers.IO).launch { zimReaderFactory.create(ZimReaderSource(file)) ?.let { zimFileReader -> BookOnDisk(zimFileReader).also { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index c5b73ca187..302822c4d2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -33,8 +33,9 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.net.toFile import androidx.drawerlayout.widget.DrawerLayout -import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomnavigation.BottomNavigationView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.cachedComponent @@ -328,7 +329,7 @@ class KiwixReaderFragment : CoreReaderFragment() { val zimReaderSource = ZimReaderSource(file) if (zimReaderSource.canOpenInLibkiwix()) { openZimFile(zimReaderSource).also { - lifecycleScope.launch { + CoroutineScope(Dispatchers.IO).launch { zimReaderFactory?.create(zimReaderSource)?.let { zimFileReader -> BooksOnDiskListItem.BookOnDisk(zimFileReader).also { bookOnDisk -> // save the book in the library From 4e3f66243ba10b5fcfd8ee68cac78a4aef0e0ac0 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 16:24:22 +0530 Subject: [PATCH 17/19] Fixed: Previously saved books are not showing on the LocalLibraryScreen. --- core/objectbox-models/default.json | 7 +++- core/objectbox-models/default.json.bak | 36 +++++++++++++------ .../kiwix/kiwixmobile/core/dao/NewBookDao.kt | 13 +++++-- .../core/dao/entities/BookOnDiskEntity.kt | 10 +++++- .../adapter/BooksOnDiskListItem.kt | 8 +++-- .../sharedFunctions/TestModelFunctions.kt | 3 +- 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/core/objectbox-models/default.json b/core/objectbox-models/default.json index 28ded888e3..06bf72f383 100644 --- a/core/objectbox-models/default.json +++ b/core/objectbox-models/default.json @@ -5,7 +5,7 @@ "entities": [ { "id": "3:5536749840871435068", - "lastPropertyId": "18:1711250046418389186", + "lastPropertyId": "19:8429535071703004578", "name": "BookOnDiskEntity", "properties": [ { @@ -88,6 +88,11 @@ "id": "18:1711250046418389186", "name": "zimReaderSource", "type": 9 + }, + { + "id": "19:8429535071703004578", + "name": "file", + "type": 9 } ], "relations": [] diff --git a/core/objectbox-models/default.json.bak b/core/objectbox-models/default.json.bak index 9c418ee2c1..28ded888e3 100644 --- a/core/objectbox-models/default.json.bak +++ b/core/objectbox-models/default.json.bak @@ -5,7 +5,7 @@ "entities": [ { "id": "3:5536749840871435068", - "lastPropertyId": "17:2701677664876214591", + "lastPropertyId": "18:1711250046418389186", "name": "BookOnDiskEntity", "properties": [ { @@ -14,11 +14,6 @@ "type": 6, "flags": 1 }, - { - "id": "2:2644395282642821815", - "name": "file", - "type": 9 - }, { "id": "4:3145196313443812205", "name": "bookId", @@ -88,6 +83,11 @@ "id": "17:2701677664876214591", "name": "tags", "type": 9 + }, + { + "id": "18:1711250046418389186", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -123,7 +123,7 @@ }, { "id": "5:3222423958972105425", - "lastPropertyId": "10:8395372122440621469", + "lastPropertyId": "11:6493253695033019145", "name": "HistoryEntity", "properties": [ { @@ -171,13 +171,18 @@ "id": "10:8395372122440621469", "name": "dateString", "type": 9 + }, + { + "id": "11:6493253695033019145", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] }, { "id": "6:2737311997994502758", - "lastPropertyId": "7:3805929017981932900", + "lastPropertyId": "8:7455000637355817969", "name": "BookmarkEntity", "properties": [ { @@ -215,6 +220,11 @@ "id": "7:3805929017981932900", "name": "favicon", "type": 9 + }, + { + "id": "8:7455000637355817969", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -250,7 +260,7 @@ }, { "id": "10:3205842982118792800", - "lastPropertyId": "9:5286545520416917562", + "lastPropertyId": "10:8943937679373521794", "name": "NotesEntity", "properties": [ { @@ -288,6 +298,11 @@ "id": "9:5286545520416917562", "name": "zimUrl", "type": 9 + }, + { + "id": "10:8943937679373521794", + "name": "zimReaderSource", + "type": 9 } ], "relations": [] @@ -378,7 +393,8 @@ 5555873126720275555, 2724607601244650879, 5485468735259326535, - 4272820830206771469 + 4272820830206771469, + 2644395282642821815 ], "retiredRelationUids": [], "version": 1 diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index 9439f86e6e..9af0bf93ed 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -35,7 +35,16 @@ class NewBookDao @Inject constructor(private val box: Box) { .map { books -> books.filter { it.zimReaderSource.exists() } } .map { it.map(::BookOnDisk) } - fun getBooks() = box.all.map(::BookOnDisk) + fun getBooks() = box.all.map { bookOnDiskEntity -> + bookOnDiskEntity.file.let { file -> + // set zimReaderSource for previously saved books + val zimReaderSource = ZimReaderSource(file) + if (zimReaderSource.canOpenInLibkiwix()) { + bookOnDiskEntity.zimReaderSource = zimReaderSource + } + } + BookOnDisk(bookOnDiskEntity) + } fun insert(booksOnDisk: List) { box.store.callInTx { @@ -83,7 +92,7 @@ class NewBookDao @Inject constructor(private val box: Box) { } private fun removeBooksThatDoNotExist(books: MutableList) { - delete(books.filterNot { it.zimReaderSource.exists() }) + delete(books.filterNot { it.zimReaderSource.exists() || it.file.exists() }) } private fun delete(books: List) { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt index 2cd30af1b6..49b134cb3d 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/BookOnDiskEntity.kt @@ -31,8 +31,10 @@ import java.io.File @Entity data class BookOnDiskEntity( @Id var id: Long = 0, + @Convert(converter = StringToFileConverter::class, dbType = String::class) + val file: File = File(""), @Convert(converter = ZimSourceConverter::class, dbType = String::class) - val zimReaderSource: ZimReaderSource, + var zimReaderSource: ZimReaderSource, val bookId: String, val title: String, val description: String?, @@ -50,6 +52,7 @@ data class BookOnDiskEntity( ) { constructor(bookOnDisk: BookOnDisk) : this( 0, + bookOnDisk.file, bookOnDisk.zimReaderSource, bookOnDisk.book.id, bookOnDisk.book.title, @@ -92,3 +95,8 @@ class ZimSourceConverter : PropertyConverter { override fun convertToEntityProperty(databaseValue: String?): ZimReaderSource = fromDatabaseValue(databaseValue) ?: ZimReaderSource(File("")) } + +class StringToFileConverter : PropertyConverter { + override fun convertToDatabaseValue(entityProperty: File?) = entityProperty?.path ?: "" + override fun convertToEntityProperty(databaseValue: String?) = File(databaseValue ?: "") +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt index 34523b7381..ec3598e5ac 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt @@ -44,6 +44,7 @@ sealed class BooksOnDiskListItem { data class BookOnDisk constructor( val databaseId: Long = 0L, val book: Book, + val file: File = File(""), val zimReaderSource: ZimReaderSource, val tags: List = KiwixTag.from(book.tags), override val id: Long = databaseId @@ -54,9 +55,10 @@ sealed class BooksOnDiskListItem { } constructor(bookOnDiskEntity: BookOnDiskEntity) : this( - bookOnDiskEntity.id, - bookOnDiskEntity.toBook(), - bookOnDiskEntity.zimReaderSource + id = bookOnDiskEntity.id, + file = bookOnDiskEntity.file, + book = bookOnDiskEntity.toBook(), + zimReaderSource = bookOnDiskEntity.zimReaderSource ) constructor(downloadRoomEntity: DownloadRoomEntity) : this( diff --git a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt index f9209504d7..a8fae21a4b 100644 --- a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt +++ b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt @@ -43,7 +43,7 @@ fun bookOnDisk( databaseId: Long = 0L, book: Book = book(), zimReaderSource: ZimReaderSource = ZimReaderSource(File("")) -) = BookOnDisk(databaseId, book, zimReaderSource) +) = BookOnDisk(databaseId, book, File(""), zimReaderSource) fun downloadModel( databaseId: Long = 1L, @@ -193,6 +193,7 @@ fun bookOnDiskEntity( ) = BookOnDiskEntity( id, + File(""), zimReaderSource, bookId, title, From 1cdd683e790a828ec78b88a69b202fe27fec6170 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 16:35:27 +0530 Subject: [PATCH 18/19] Improved the `books()` method to properly return the new books along with the old saved books. --- .../org/kiwix/kiwixmobile/core/dao/NewBookDao.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index 9af0bf93ed..96fd199077 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -31,7 +31,19 @@ import javax.inject.Inject class NewBookDao @Inject constructor(private val box: Box) { fun books() = box.asFlowable() - .doOnNext(::removeBooksThatDoNotExist) + .map { books -> + books.map { bookOnDiskEntity -> + bookOnDiskEntity.file.let { file -> + // set zimReaderSource for previously saved books + val zimReaderSource = ZimReaderSource(file) + if (zimReaderSource.canOpenInLibkiwix()) { + bookOnDiskEntity.zimReaderSource = zimReaderSource + } + } + bookOnDiskEntity + } + } + .doOnNext { removeBooksThatDoNotExist(it.toMutableList()) } .map { books -> books.filter { it.zimReaderSource.exists() } } .map { it.map(::BookOnDisk) } @@ -92,7 +104,7 @@ class NewBookDao @Inject constructor(private val box: Box) { } private fun removeBooksThatDoNotExist(books: MutableList) { - delete(books.filterNot { it.zimReaderSource.exists() || it.file.exists() }) + delete(books.filterNot { it.zimReaderSource.exists() }) } private fun delete(books: List) { From 2d0bc4855df13040fb58d5527073866de43f42a9 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sun, 25 Aug 2024 19:31:21 +0530 Subject: [PATCH 19/19] * Fixed: Deleting files was not working in the local library. * Removed the unnecessary comments. --- .../java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt | 4 ---- .../fileselect_view/adapter/BooksOnDiskListItem.kt | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index d6ff581192..58a89a6c70 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -196,11 +196,7 @@ abstract class KiwixRoomDatabase : RoomDatabase() { FROM HistoryRoomEntity """ ) - - // Step 3: Drop the old table database.execSQL("DROP TABLE HistoryRoomEntity") - - // Step 4: Rename the new table to the old table's name database.execSQL("ALTER TABLE HistoryRoomEntity_temp RENAME TO HistoryRoomEntity") database.execSQL("ALTER TABLE NotesRoomEntity ADD COLUMN zimReaderSource TEXT") } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt index ec3598e5ac..700f28441f 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/zim_manager/fileselect_view/adapter/BooksOnDiskListItem.kt @@ -55,7 +55,7 @@ sealed class BooksOnDiskListItem { } constructor(bookOnDiskEntity: BookOnDiskEntity) : this( - id = bookOnDiskEntity.id, + databaseId = bookOnDiskEntity.id, file = bookOnDiskEntity.file, book = bookOnDiskEntity.toBook(), zimReaderSource = bookOnDiskEntity.zimReaderSource