mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-24 05:04:50 -04:00
Merge pull request #4396 from kiwix/remove_objectbox_code_from_project
Removed ObjectBox code from the project (except migration-related code).
This commit is contained in:
commit
b827cfe542
@ -17,7 +17,6 @@
|
|||||||
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$override fun exchangeFileTransferMetadata(inputStream: InputStream, outputStream: OutputStream)</ID>
|
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$override fun exchangeFileTransferMetadata(inputStream: InputStream, outputStream: OutputStream)</ID>
|
||||||
<ID>PackageNaming:AvailableSpaceCalculator.kt$package
|
<ID>PackageNaming:AvailableSpaceCalculator.kt$package
|
||||||
org.kiwix.kiwixmobile.zimManager.libraryView</ID>
|
org.kiwix.kiwixmobile.zimManager.libraryView</ID>
|
||||||
<ID>PackageNaming:DefaultLanguageProvider.kt$package org.kiwix.kiwixmobile.zimManager</ID>
|
|
||||||
<ID>PackageNaming:DeleteFiles.kt$package
|
<ID>PackageNaming:DeleteFiles.kt$package
|
||||||
org.kiwix.kiwixmobile.zimManager.fileselectView.effects</ID>
|
org.kiwix.kiwixmobile.zimManager.fileselectView.effects</ID>
|
||||||
<ID>PackageNaming:Fat32Checker.kt$package org.kiwix.kiwixmobile.zimManager</ID>
|
<ID>PackageNaming:Fat32Checker.kt$package org.kiwix.kiwixmobile.zimManager</ID>
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
|
||||||
import kotlinx.coroutines.channels.trySendBlocking
|
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class FlowBuilder @Inject constructor() {
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun <T> buildCallbackFlow(query: Query<T>) =
|
|
||||||
callbackFlow<List<T>> {
|
|
||||||
val subscription =
|
|
||||||
query.subscribe()
|
|
||||||
.observer { trySendBlocking(it) }
|
|
||||||
awaitClose(subscription::cancel)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
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<HistoryEntity>) : PageDao {
|
|
||||||
fun history(): Flow<List<Page>> =
|
|
||||||
box.asFlow(
|
|
||||||
box.query {
|
|
||||||
orderDesc(HistoryEntity_.timeStamp)
|
|
||||||
}
|
|
||||||
).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(): Flow<List<Page>> = history()
|
|
||||||
override fun deletePages(pagesToDelete: List<Page>) =
|
|
||||||
deleteHistory(pagesToDelete as List<HistoryItem>)
|
|
||||||
|
|
||||||
fun saveHistory(historyItem: HistoryItem) {
|
|
||||||
box.store.callInTx {
|
|
||||||
box
|
|
||||||
.query {
|
|
||||||
equal(
|
|
||||||
HistoryEntity_.historyUrl,
|
|
||||||
historyItem.historyUrl,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
).and()
|
|
||||||
.equal(
|
|
||||||
HistoryEntity_.dateString,
|
|
||||||
historyItem.dateString,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.remove()
|
|
||||||
box.put(HistoryEntity(historyItem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteHistory(historyList: List<HistoryItem>) {
|
|
||||||
box.remove(historyList.map(::HistoryEntity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAllHistory() {
|
|
||||||
box.removeAll()
|
|
||||||
}
|
|
||||||
}
|
|
@ -212,7 +212,6 @@ class LibkiwixBookOnDisk @Inject constructor(
|
|||||||
}
|
}
|
||||||
}.onFailure { it.printStackTrace() }
|
}.onFailure { it.printStackTrace() }
|
||||||
writeBookMarksAndSaveLibraryToFile()
|
writeBookMarksAndSaveLibraryToFile()
|
||||||
// TODO test when getting books it will not goes to circular dependencies mode.
|
|
||||||
updateLocalBooksFlow()
|
updateLocalBooksFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.inValues
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_
|
|
||||||
import org.kiwix.kiwixmobile.core.entity.LibkiwixBook
|
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
@Suppress("Deprecation")
|
|
||||||
fun books(dispatcher: CoroutineDispatcher = Dispatchers.IO) =
|
|
||||||
box.asFlow()
|
|
||||||
.mapLatest { booksList ->
|
|
||||||
val updatedBooks = booksList.onEach { bookOnDiskEntity ->
|
|
||||||
val file = bookOnDiskEntity.file
|
|
||||||
val zimReaderSource = ZimReaderSource(file)
|
|
||||||
try {
|
|
||||||
if (zimReaderSource.canOpenInLibkiwix()) {
|
|
||||||
bookOnDiskEntity.zimReaderSource = zimReaderSource
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
// Do nothing simply return the bookOnDiskEntity.
|
|
||||||
}
|
|
||||||
bookOnDiskEntity
|
|
||||||
}
|
|
||||||
removeBooksThatAreInTrashFolder(updatedBooks)
|
|
||||||
removeBooksThatDoNotExist(updatedBooks.toMutableList())
|
|
||||||
|
|
||||||
updatedBooks.mapNotNull { book ->
|
|
||||||
try {
|
|
||||||
if (book.zimReaderSource.exists() &&
|
|
||||||
!isInTrashFolder(book.zimReaderSource.toDatabase())
|
|
||||||
) {
|
|
||||||
book
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.map { it.map(::BookOnDisk) }
|
|
||||||
.flowOn(dispatcher)
|
|
||||||
|
|
||||||
@Suppress("Deprecation")
|
|
||||||
suspend 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<BookOnDisk>) {
|
|
||||||
box.store.callInTx {
|
|
||||||
val uniqueBooks = uniqueBooksByFile(booksOnDisk)
|
|
||||||
removeEntriesWithMatchingIds(uniqueBooks)
|
|
||||||
box.put(uniqueBooks.distinctBy { it.book.id }.map(::BookOnDiskEntity))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun uniqueBooksByFile(booksOnDisk: List<BookOnDisk>): List<BookOnDisk> {
|
|
||||||
val booksWithSameFilePath = booksWithSameFilePath(booksOnDisk)
|
|
||||||
return booksOnDisk.filter { bookOnDisk: BookOnDisk ->
|
|
||||||
booksWithSameFilePath.none { it.zimReaderSource == bookOnDisk.zimReaderSource }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("Deprecation")
|
|
||||||
private fun booksWithSameFilePath(booksOnDisk: List<BookOnDisk>) =
|
|
||||||
box.query {
|
|
||||||
inValues(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
booksOnDisk.map { it.zimReaderSource.toDatabase() }.toTypedArray(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}.find()
|
|
||||||
.map(::BookOnDisk)
|
|
||||||
|
|
||||||
private fun removeEntriesWithMatchingIds(uniqueBooks: List<BookOnDisk>) {
|
|
||||||
box.query {
|
|
||||||
inValues(
|
|
||||||
BookOnDiskEntity_.bookId,
|
|
||||||
uniqueBooks.map { it.book.id }.toTypedArray(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun delete(databaseId: Long) {
|
|
||||||
box.remove(databaseId)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UnsafeCallOnNullableType")
|
|
||||||
fun migrationInsert(books: List<LibkiwixBook>) {
|
|
||||||
insert(books.map { BookOnDisk(book = it, zimReaderSource = ZimReaderSource(it.file!!)) })
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun removeBooksThatDoNotExist(books: MutableList<BookOnDiskEntity>) {
|
|
||||||
delete(books.filterNot { it.zimReaderSource.exists() })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the existing books from database which are showing on the library screen.
|
|
||||||
private fun removeBooksThatAreInTrashFolder(books: List<BookOnDiskEntity>) {
|
|
||||||
delete(books.filter { isInTrashFolder(it.zimReaderSource.toDatabase()) })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any existing ZIM file showing on the library screen which is inside the trash folder.
|
|
||||||
private fun isInTrashFolder(filePath: String) =
|
|
||||||
Regex("/\\.Trash/").containsMatchIn(filePath)
|
|
||||||
|
|
||||||
private fun delete(books: List<BookOnDiskEntity>) {
|
|
||||||
box.remove(books)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bookMatching(downloadTitle: String) =
|
|
||||||
box.query {
|
|
||||||
endsWith(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
downloadTitle,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}.findFirst()
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
|
||||||
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<BookmarkEntity>) : PageDao {
|
|
||||||
fun bookmarks(): Flow<List<Page>> =
|
|
||||||
box.asFlow(
|
|
||||||
box.query {
|
|
||||||
order(BookmarkEntity_.bookmarkTitle)
|
|
||||||
}
|
|
||||||
).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(): Flow<List<Page>> = bookmarks()
|
|
||||||
override fun deletePages(pagesToDelete: List<Page>) =
|
|
||||||
deleteBookmarks(pagesToDelete as List<BookmarkItem>)
|
|
||||||
|
|
||||||
fun getCurrentZimBookmarksUrl(zimFileReader: ZimFileReader?) =
|
|
||||||
box.query {
|
|
||||||
equal(
|
|
||||||
BookmarkEntity_.zimId,
|
|
||||||
zimFileReader?.id.orEmpty(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
.or()
|
|
||||||
.equal(
|
|
||||||
BookmarkEntity_.zimName,
|
|
||||||
zimFileReader?.name.orEmpty(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
order(BookmarkEntity_.bookmarkTitle)
|
|
||||||
}.property(BookmarkEntity_.bookmarkUrl)
|
|
||||||
.findStrings()
|
|
||||||
.toList()
|
|
||||||
.distinct()
|
|
||||||
|
|
||||||
fun bookmarkUrlsForCurrentBook(
|
|
||||||
zimFileReader: ZimFileReader?,
|
|
||||||
dispatcher: CoroutineDispatcher = Dispatchers.IO
|
|
||||||
): Flow<List<String>> =
|
|
||||||
box.asFlow(
|
|
||||||
box.query {
|
|
||||||
equal(
|
|
||||||
BookmarkEntity_.zimId,
|
|
||||||
zimFileReader?.id.orEmpty(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
.or()
|
|
||||||
.equal(
|
|
||||||
BookmarkEntity_.zimName,
|
|
||||||
zimFileReader?.name.orEmpty(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
order(BookmarkEntity_.bookmarkTitle)
|
|
||||||
}
|
|
||||||
).map { it.map(BookmarkEntity::bookmarkUrl) }
|
|
||||||
.flowOn(dispatcher)
|
|
||||||
|
|
||||||
fun saveBookmark(bookmarkItem: BookmarkItem) {
|
|
||||||
box.put(BookmarkEntity(bookmarkItem))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteBookmarks(bookmarks: List<BookmarkItem>) {
|
|
||||||
box.remove(bookmarks.map(::BookmarkEntity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteBookmark(bookmarkUrl: String) {
|
|
||||||
box.query {
|
|
||||||
equal(
|
|
||||||
BookmarkEntity_.bookmarkUrl,
|
|
||||||
bookmarkUrl,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}.remove()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.flow
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.LanguageEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class NewLanguagesDao @Inject constructor(private val box: Box<LanguageEntity>) {
|
|
||||||
fun languages() =
|
|
||||||
box.asFlow()
|
|
||||||
.map { it.map(LanguageEntity::toLanguageModel) }
|
|
||||||
|
|
||||||
fun insert(languages: List<Language>) {
|
|
||||||
box.store.callInTx {
|
|
||||||
box.removeAll()
|
|
||||||
box.put(languages.map(::LanguageEntity))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
fun <T> Box<T>.asFlow(query: Query<T> = query {}): Flow<List<T>> {
|
|
||||||
return query.flow()
|
|
||||||
.map { it.toList() }
|
|
||||||
.distinctUntilChanged()
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
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<NotesEntity>) : PageDao {
|
|
||||||
fun notes(): Flow<List<Page>> =
|
|
||||||
box.asFlow(
|
|
||||||
box.query {
|
|
||||||
order(NotesEntity_.noteTitle)
|
|
||||||
}
|
|
||||||
).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(): Flow<List<Page>> = notes()
|
|
||||||
|
|
||||||
override fun deletePages(pagesToDelete: List<Page>) =
|
|
||||||
deleteNotes(pagesToDelete as List<NoteListItem>)
|
|
||||||
|
|
||||||
fun saveNote(noteItem: NoteListItem) {
|
|
||||||
box.store.callInTx {
|
|
||||||
if (doesNotAlreadyExist(noteItem)) {
|
|
||||||
box.put(NotesEntity(noteItem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteNotes(noteList: List<NoteListItem>) {
|
|
||||||
box.remove(noteList.map(::NotesEntity))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteNote(noteUniqueKey: String) {
|
|
||||||
box.query {
|
|
||||||
equal(
|
|
||||||
NotesEntity_.noteTitle,
|
|
||||||
noteUniqueKey,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doesNotAlreadyExist(noteItem: NoteListItem) =
|
|
||||||
box.query {
|
|
||||||
equal(NotesEntity_.noteTitle, noteItem.title, QueryBuilder.StringOrder.CASE_INSENSITIVE)
|
|
||||||
}.count() == 0L
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.kotlin.query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity_
|
|
||||||
import org.kiwix.kiwixmobile.core.search.SearchListItem.RecentSearchListItem
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class NewRecentSearchDao @Inject constructor(
|
|
||||||
private val box: Box<RecentSearchEntity>,
|
|
||||||
private val flowBuilder: FlowBuilder
|
|
||||||
) {
|
|
||||||
fun recentSearches(zimId: String?) =
|
|
||||||
flowBuilder.buildCallbackFlow(
|
|
||||||
box.query {
|
|
||||||
equal(
|
|
||||||
RecentSearchEntity_.zimId,
|
|
||||||
zimId.orEmpty(),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
orderDesc(RecentSearchEntity_.id)
|
|
||||||
}
|
|
||||||
).map { searchEntities ->
|
|
||||||
searchEntities.distinctBy(RecentSearchEntity::searchTerm)
|
|
||||||
.take(NUM_RECENT_RESULTS)
|
|
||||||
.map { searchEntity -> RecentSearchListItem(searchEntity.searchTerm, searchEntity.url) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveSearch(title: String, id: String, url: String?) {
|
|
||||||
box.put(RecentSearchEntity(searchTerm = title, zimId = id, url = url))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteSearchString(searchTerm: String) {
|
|
||||||
box
|
|
||||||
.query {
|
|
||||||
equal(
|
|
||||||
RecentSearchEntity_.searchTerm,
|
|
||||||
searchTerm,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteSearchHistory() {
|
|
||||||
box.removeAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val NUM_RECENT_RESULTS = 100
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,11 +20,11 @@ package org.kiwix.kiwixmobile.core.dao.entities
|
|||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import androidx.room.TypeConverter
|
||||||
|
import androidx.room.TypeConverters
|
||||||
import com.tonyodev.fetch2.Download
|
import com.tonyodev.fetch2.Download
|
||||||
import com.tonyodev.fetch2.Error
|
import com.tonyodev.fetch2.Error
|
||||||
import com.tonyodev.fetch2.Status
|
import com.tonyodev.fetch2.Status
|
||||||
import io.objectbox.annotation.Convert
|
|
||||||
import io.objectbox.converter.PropertyConverter
|
|
||||||
import org.kiwix.kiwixmobile.core.entity.LibkiwixBook
|
import org.kiwix.kiwixmobile.core.entity.LibkiwixBook
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@ -36,9 +36,9 @@ data class DownloadRoomEntity(
|
|||||||
val etaInMilliSeconds: Long = -1L,
|
val etaInMilliSeconds: Long = -1L,
|
||||||
val bytesDownloaded: Long = -1L,
|
val bytesDownloaded: Long = -1L,
|
||||||
val totalSizeOfDownload: Long = -1L,
|
val totalSizeOfDownload: Long = -1L,
|
||||||
@Convert(converter = StatusConverter::class, dbType = Int::class)
|
@TypeConverters(StatusConverter::class)
|
||||||
val status: Status = Status.NONE,
|
val status: Status = Status.NONE,
|
||||||
@Convert(converter = ErrorConverter::class, dbType = Int::class)
|
@TypeConverters(ErrorConverter::class)
|
||||||
val error: Error = Error.NONE,
|
val error: Error = Error.NONE,
|
||||||
val progress: Int = -1,
|
val progress: Int = -1,
|
||||||
val bookId: String,
|
val bookId: String,
|
||||||
@ -104,14 +104,18 @@ data class DownloadRoomEntity(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class StatusConverter : EnumConverter<Status>() {
|
class StatusConverter {
|
||||||
override fun convertToEntityProperty(databaseValue: Int) = Status.valueOf(databaseValue)
|
@TypeConverter
|
||||||
|
fun convertToEntityProperty(databaseValue: Int): Status = Status.valueOf(databaseValue)
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun convertToDatabaseValue(status: Status): Int = status.ordinal
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErrorConverter : EnumConverter<Error>() {
|
class ErrorConverter {
|
||||||
override fun convertToEntityProperty(databaseValue: Int) = Error.valueOf(databaseValue)
|
@TypeConverter
|
||||||
}
|
fun convertToEntityProperty(databaseValue: Int) = Error.valueOf(databaseValue)
|
||||||
|
|
||||||
abstract class EnumConverter<E : Enum<E>> : PropertyConverter<E, Int> {
|
@TypeConverter
|
||||||
override fun convertToDatabaseValue(entityProperty: E): Int = entityProperty.ordinal
|
fun convertToDatabaseValue(error: Error): Int = error.ordinal
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,11 @@ import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao
|
|||||||
import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao
|
import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BundleRoomConverter
|
import org.kiwix.kiwixmobile.core.dao.entities.BundleRoomConverter
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.entities.ErrorConverter
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.entities.StatusConverter
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter
|
import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter
|
||||||
|
|
||||||
@ -48,13 +50,15 @@ import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter
|
|||||||
DownloadRoomEntity::class,
|
DownloadRoomEntity::class,
|
||||||
WebViewHistoryEntity::class
|
WebViewHistoryEntity::class
|
||||||
],
|
],
|
||||||
version = 8,
|
version = 9,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
@TypeConverters(
|
@TypeConverters(
|
||||||
HistoryRoomDaoCoverts::class,
|
HistoryRoomDaoCoverts::class,
|
||||||
ZimSourceRoomConverter::class,
|
ZimSourceRoomConverter::class,
|
||||||
BundleRoomConverter::class
|
BundleRoomConverter::class,
|
||||||
|
StatusConverter::class,
|
||||||
|
ErrorConverter::class
|
||||||
)
|
)
|
||||||
abstract class KiwixRoomDatabase : RoomDatabase() {
|
abstract class KiwixRoomDatabase : RoomDatabase() {
|
||||||
abstract fun recentSearchRoomDao(): RecentSearchRoomDao
|
abstract fun recentSearchRoomDao(): RecentSearchRoomDao
|
||||||
@ -78,7 +82,8 @@ abstract class KiwixRoomDatabase : RoomDatabase() {
|
|||||||
MIGRATION_4_5,
|
MIGRATION_4_5,
|
||||||
MIGRATION_5_6,
|
MIGRATION_5_6,
|
||||||
MIGRATION_6_7,
|
MIGRATION_6_7,
|
||||||
MIGRATION_7_8
|
MIGRATION_7_8,
|
||||||
|
MIGRATION_8_9
|
||||||
)
|
)
|
||||||
.build().also { db = it }
|
.build().also { db = it }
|
||||||
}
|
}
|
||||||
@ -305,6 +310,60 @@ abstract class KiwixRoomDatabase : RoomDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private val MIGRATION_8_9 =
|
||||||
|
object : Migration(8, 9) {
|
||||||
|
override fun migrate(db: SupportSQLiteDatabase) {
|
||||||
|
db.execSQL(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS DownloadRoomEntity_new (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
downloadId INTEGER NOT NULL,
|
||||||
|
file TEXT,
|
||||||
|
etaInMilliSeconds INTEGER NOT NULL DEFAULT -1,
|
||||||
|
bytesDownloaded INTEGER NOT NULL DEFAULT -1,
|
||||||
|
totalSizeOfDownload INTEGER NOT NULL DEFAULT -1,
|
||||||
|
status INTEGER NOT NULL DEFAULT 0,
|
||||||
|
error INTEGER NOT NULL DEFAULT 0,
|
||||||
|
progress INTEGER NOT NULL DEFAULT -1,
|
||||||
|
bookId TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
language TEXT NOT NULL,
|
||||||
|
creator TEXT NOT NULL,
|
||||||
|
publisher TEXT NOT NULL,
|
||||||
|
date TEXT NOT NULL,
|
||||||
|
url TEXT,
|
||||||
|
articleCount TEXT,
|
||||||
|
mediaCount TEXT,
|
||||||
|
size TEXT NOT NULL,
|
||||||
|
name TEXT,
|
||||||
|
favIcon TEXT NOT NULL,
|
||||||
|
tags TEXT
|
||||||
|
)
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
db.execSQL(
|
||||||
|
"""
|
||||||
|
INSERT INTO DownloadRoomEntity_new (
|
||||||
|
id, downloadId, file, etaInMilliSeconds, bytesDownloaded,
|
||||||
|
totalSizeOfDownload, status, error, progress, bookId, title,
|
||||||
|
description, language, creator, publisher, date, url,
|
||||||
|
articleCount, mediaCount, size, name, favIcon, tags
|
||||||
|
)
|
||||||
|
SELECT id, downloadId, file, etaInMilliSeconds, bytesDownloaded,
|
||||||
|
totalSizeOfDownload, status, error, progress, bookId, title, description,
|
||||||
|
language, creator, publisher, date, url, articleCount,
|
||||||
|
mediaCount, size, name, favIcon, tags
|
||||||
|
FROM DownloadRoomEntity
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
db.execSQL("DROP TABLE DownloadRoomEntity")
|
||||||
|
db.execSQL("ALTER TABLE DownloadRoomEntity_new RENAME TO DownloadRoomEntity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun destroyInstance() {
|
fun destroyInstance() {
|
||||||
db = null
|
db = null
|
||||||
}
|
}
|
||||||
|
@ -28,15 +28,9 @@ import org.kiwix.kiwixmobile.core.CoreApp
|
|||||||
import org.kiwix.kiwixmobile.core.LibkiwixBookFactory
|
import org.kiwix.kiwixmobile.core.LibkiwixBookFactory
|
||||||
import org.kiwix.kiwixmobile.core.StorageObserver
|
import org.kiwix.kiwixmobile.core.StorageObserver
|
||||||
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao
|
import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewNoteDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
|
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao
|
import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao
|
import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao
|
||||||
@ -92,13 +86,7 @@ interface CoreComponent {
|
|||||||
fun application(): Application
|
fun application(): Application
|
||||||
fun bookUtils(): BookUtils
|
fun bookUtils(): BookUtils
|
||||||
fun dataSource(): DataSource
|
fun dataSource(): DataSource
|
||||||
fun newBookDao(): NewBookDao
|
|
||||||
fun historyDao(): HistoryDao
|
|
||||||
fun noteDao(): NewNoteDao
|
|
||||||
fun newLanguagesDao(): NewLanguagesDao
|
|
||||||
fun recentSearchDao(): NewRecentSearchDao
|
|
||||||
fun downloadRoomDao(): DownloadRoomDao
|
fun downloadRoomDao(): DownloadRoomDao
|
||||||
fun newBookmarksDao(): NewBookmarksDao
|
|
||||||
fun connectivityManager(): ConnectivityManager
|
fun connectivityManager(): ConnectivityManager
|
||||||
fun objectBoxToLibkiwixMigrator(): ObjectBoxToLibkiwixMigrator
|
fun objectBoxToLibkiwixMigrator(): ObjectBoxToLibkiwixMigrator
|
||||||
fun libkiwixBookmarks(): LibkiwixBookmarks
|
fun libkiwixBookmarks(): LibkiwixBookmarks
|
||||||
|
@ -21,15 +21,7 @@ import android.content.Context
|
|||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import io.objectbox.BoxStore
|
import io.objectbox.BoxStore
|
||||||
import io.objectbox.kotlin.boxFor
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.FlowBuilder
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewNoteDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.MyObjectBox
|
import org.kiwix.kiwixmobile.core.dao.entities.MyObjectBox
|
||||||
import org.kiwix.kiwixmobile.core.data.KiwixRoomDatabase
|
import org.kiwix.kiwixmobile.core.data.KiwixRoomDatabase
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -49,26 +41,6 @@ open class DatabaseModule {
|
|||||||
return boxStore!!
|
return boxStore!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewBookDao(boxStore: BoxStore): NewBookDao =
|
|
||||||
NewBookDao(boxStore.boxFor())
|
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewLanguagesDao(boxStore: BoxStore): NewLanguagesDao =
|
|
||||||
NewLanguagesDao(boxStore.boxFor())
|
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewHistoryDao(boxStore: BoxStore): HistoryDao =
|
|
||||||
HistoryDao(boxStore.boxFor())
|
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewBookmarksDao(boxStore: BoxStore): NewBookmarksDao =
|
|
||||||
NewBookmarksDao(boxStore.boxFor())
|
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewNoteDao(boxStore: BoxStore): NewNoteDao =
|
|
||||||
NewNoteDao(boxStore.boxFor())
|
|
||||||
|
|
||||||
@Provides @Singleton fun providesNewRecentSearchDao(
|
|
||||||
boxStore: BoxStore,
|
|
||||||
flowBuilder: FlowBuilder
|
|
||||||
): NewRecentSearchDao = NewRecentSearchDao(boxStore.boxFor(), flowBuilder)
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideYourDatabase(
|
fun provideYourDatabase(
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2021 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.mockk.CapturingSlot
|
|
||||||
import io.mockk.clearAllMocks
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.slot
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import org.junit.jupiter.api.AfterEach
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
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 {
|
|
||||||
private val box: Box<HistoryEntity> = mockk(relaxed = true)
|
|
||||||
private val historyDao = HistoryDao(box)
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
fun tearDown() {
|
|
||||||
clearAllMocks()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deletePages() {
|
|
||||||
val historyItem: HistoryListItem.HistoryItem = historyItem(zimReaderSource = mockk())
|
|
||||||
val historyItemList: List<HistoryListItem.HistoryItem> = listOf(historyItem)
|
|
||||||
val pagesToDelete: List<Page> = historyItemList
|
|
||||||
historyDao.deletePages(pagesToDelete)
|
|
||||||
verify { historyDao.deleteHistory(historyItemList) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveHistory() {
|
|
||||||
val historyItem: HistoryListItem.HistoryItem =
|
|
||||||
historyItem(
|
|
||||||
historyUrl = "",
|
|
||||||
dateString = "",
|
|
||||||
zimReaderSource = mockk()
|
|
||||||
)
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
val queryBuilder: QueryBuilder<HistoryEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(HistoryEntity_.historyUrl, "", QueryBuilder.StringOrder.CASE_INSENSITIVE)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.and() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
HistoryEntity_.dateString,
|
|
||||||
"",
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<HistoryEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
historyDao.saveHistory(historyItem)
|
|
||||||
slot.captured.call()
|
|
||||||
verify { query.remove() }
|
|
||||||
verify { box.put(HistoryEntity(historyItem)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deleteAllHistory() {
|
|
||||||
historyDao.deleteAllHistory()
|
|
||||||
verify { box.removeAll() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.mockk.CapturingSlot
|
|
||||||
import io.mockk.clearAllMocks
|
|
||||||
import io.mockk.coEvery
|
|
||||||
import io.mockk.coVerify
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.mockkStatic
|
|
||||||
import io.mockk.slot
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import io.objectbox.reactive.SubscriptionBuilder
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.jupiter.api.Assertions
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
|
||||||
import org.junit.jupiter.api.Nested
|
|
||||||
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.LibkiwixBook
|
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.testFlow
|
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk
|
|
||||||
import org.kiwix.sharedFunctions.bookOnDisk
|
|
||||||
import org.kiwix.sharedFunctions.bookOnDiskEntity
|
|
||||||
import org.kiwix.sharedFunctions.libkiwixBook
|
|
||||||
import java.io.File
|
|
||||||
import java.util.concurrent.Callable
|
|
||||||
|
|
||||||
const val MOCKK_TIMEOUT_FOR_VERIFICATION = 1000L
|
|
||||||
|
|
||||||
internal class NewBookDaoTest {
|
|
||||||
private val box: Box<BookOnDiskEntity> = mockk(relaxed = true)
|
|
||||||
private val newBookDao = NewBookDao(box)
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
internal fun setUp() {
|
|
||||||
clearAllMocks()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
inner class BooksTests {
|
|
||||||
@Test
|
|
||||||
fun `books emits entities whose file exists`() = flakyTest {
|
|
||||||
runTest {
|
|
||||||
val (expectedEntity, _) = expectEmissionOfExistingAndNotExistingBook()
|
|
||||||
testFlow(
|
|
||||||
flow = newBookDao.books(),
|
|
||||||
triggerAction = {},
|
|
||||||
assert = { assertThat(awaitItem()).contains(BookOnDisk(expectedEntity)) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `books deletes entities whose file does not exist`() = flakyTest {
|
|
||||||
runTest {
|
|
||||||
val (_, deletedEntity) = expectEmissionOfExistingAndNotExistingBook()
|
|
||||||
testFlow(
|
|
||||||
flow = newBookDao.books(),
|
|
||||||
triggerAction = {},
|
|
||||||
assert = {
|
|
||||||
coVerify(timeout = MOCKK_TIMEOUT_FOR_VERIFICATION) {
|
|
||||||
box.remove(listOf(deletedEntity))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `books removes entities whose files are in the trash folder`() = flakyTest {
|
|
||||||
runTest {
|
|
||||||
val (_, _) = expectEmissionOfExistingAndNotExistingBook(true)
|
|
||||||
testFlow(
|
|
||||||
flow = newBookDao.books(),
|
|
||||||
triggerAction = {},
|
|
||||||
assert = { Assertions.assertEquals(emptyList<BookOnDisk>(), awaitItem()) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
private fun expectEmissionOfExistingAndNotExistingBook(
|
|
||||||
isInTrashFolder: Boolean = false
|
|
||||||
): Pair<BookOnDiskEntity, BookOnDiskEntity> {
|
|
||||||
val query: Query<BookOnDiskEntity> = mockk()
|
|
||||||
val subscriptionBuilder: SubscriptionBuilder<MutableList<BookOnDiskEntity>> =
|
|
||||||
mockk(relaxed = true)
|
|
||||||
every { box.query().build() } returns query
|
|
||||||
every { query.subscribe() } returns subscriptionBuilder
|
|
||||||
val zimReaderSourceThatExists = mockk<ZimReaderSource>()
|
|
||||||
val zimReaderSourceThatDoesNotExist = mockk<ZimReaderSource>()
|
|
||||||
coEvery { zimReaderSourceThatExists.exists() } returns true
|
|
||||||
coEvery { zimReaderSourceThatDoesNotExist.exists() } returns false
|
|
||||||
every {
|
|
||||||
zimReaderSourceThatExists.toDatabase()
|
|
||||||
} returns if (isInTrashFolder) "/.Trash/test.zim" else ""
|
|
||||||
every { zimReaderSourceThatDoesNotExist.toDatabase() } returns ""
|
|
||||||
val entityThatExists = bookOnDiskEntity(zimReaderSource = zimReaderSourceThatExists)
|
|
||||||
val entityThatDoesNotExist =
|
|
||||||
bookOnDiskEntity(zimReaderSource = zimReaderSourceThatDoesNotExist)
|
|
||||||
mockkStatic(Query::class)
|
|
||||||
mockBoxAsFlow(box, mutableListOf(entityThatExists, entityThatDoesNotExist))
|
|
||||||
return entityThatExists to entityThatDoesNotExist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getBooks() =
|
|
||||||
runTest {
|
|
||||||
val entity = bookOnDiskEntity()
|
|
||||||
every { box.all } returns mutableListOf(entity)
|
|
||||||
assertThat(newBookDao.getBooks()).isEqualTo(listOf(BookOnDisk(entity)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
inner class Insertion {
|
|
||||||
@Test
|
|
||||||
fun `insert transaction adds books to the box that have distinct ids`() {
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
val distinctBook: BookOnDisk = bookOnDisk(databaseId = 0, book = libkiwixBook(id = "same"))
|
|
||||||
newBookDao.insert(
|
|
||||||
listOf(distinctBook, bookOnDisk(databaseId = 1, book = libkiwixBook(id = "same")))
|
|
||||||
)
|
|
||||||
val queryBuilder: QueryBuilder<BookOnDiskEntity> = mockk(relaxed = true)
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.`in`(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
arrayOf(distinctBook.zimReaderSource.toDatabase()),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<BookOnDiskEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every {
|
|
||||||
query.find()
|
|
||||||
} returns listOf(bookOnDiskEntity(zimReaderSource = ZimReaderSource(File("matches_nothing"))))
|
|
||||||
slot.captured.call()
|
|
||||||
verify { box.put(listOf(BookOnDiskEntity(distinctBook))) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `insert transaction does not add books if a book with the same path exists in the box`() {
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
val distinctBook: BookOnDisk = bookOnDisk()
|
|
||||||
newBookDao.insert(listOf(distinctBook))
|
|
||||||
val queryBuilder: QueryBuilder<BookOnDiskEntity> = mockk(relaxed = true)
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.`in`(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
arrayOf(distinctBook.zimReaderSource.toDatabase()),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<BookOnDiskEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every {
|
|
||||||
query.find()
|
|
||||||
} returns listOf(bookOnDiskEntity(zimReaderSource = distinctBook.zimReaderSource))
|
|
||||||
slot.captured.call()
|
|
||||||
verify { box.put(listOf()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `insert transaction removes books with duplicate ids`() {
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
val distinctBook: BookOnDisk = bookOnDisk()
|
|
||||||
newBookDao.insert(listOf(distinctBook))
|
|
||||||
val queryBuilder: QueryBuilder<BookOnDiskEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.`in`(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
arrayOf(distinctBook.zimReaderSource.toDatabase()),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<BookOnDiskEntity> = mockk()
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every { query.find() } returns listOf()
|
|
||||||
every {
|
|
||||||
queryBuilder.`in`(
|
|
||||||
BookOnDiskEntity_.bookId,
|
|
||||||
arrayOf(distinctBook.book.id),
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { query.remove() } returns 0L
|
|
||||||
slot.captured.call()
|
|
||||||
verify { box.put(listOf(BookOnDiskEntity(distinctBook))) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun delete() {
|
|
||||||
newBookDao.delete(0L)
|
|
||||||
verify { box.remove(0L) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun migrationInsert() {
|
|
||||||
val book: LibkiwixBook = libkiwixBook()
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
newBookDao.migrationInsert(listOf(book))
|
|
||||||
slot.captured.call()
|
|
||||||
verify {
|
|
||||||
box.put(
|
|
||||||
listOf(
|
|
||||||
BookOnDiskEntity(
|
|
||||||
BookOnDisk(
|
|
||||||
book = book,
|
|
||||||
zimReaderSource = ZimReaderSource(book.file!!)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `bookMatching queries file by title`() {
|
|
||||||
val downloadTitle = "title"
|
|
||||||
val queryBuilder: QueryBuilder<BookOnDiskEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.endsWith(
|
|
||||||
BookOnDiskEntity_.zimReaderSource,
|
|
||||||
downloadTitle,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<BookOnDiskEntity> = mockk()
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
val bookOnDiskEntity: BookOnDiskEntity = bookOnDiskEntity()
|
|
||||||
every { query.findFirst() } returns bookOnDiskEntity
|
|
||||||
assertThat(newBookDao.bookMatching(downloadTitle)).isEqualTo(bookOnDiskEntity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> mockBoxAsFlow(box: Box<T>, result: List<T>) {
|
|
||||||
mockkStatic("org.kiwix.kiwixmobile.core.dao.NewLanguagesDaoKt")
|
|
||||||
every { box.asFlow(any()) } returns flow { emit(result) }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun flakyTest(
|
|
||||||
maxRetries: Int = 10,
|
|
||||||
delayMillis: Long = 0,
|
|
||||||
block: () -> Unit
|
|
||||||
) {
|
|
||||||
var lastError: Throwable? = null
|
|
||||||
|
|
||||||
repeat(maxRetries) { attempt ->
|
|
||||||
try {
|
|
||||||
block()
|
|
||||||
return
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
lastError = e
|
|
||||||
println("Test attempt ${attempt + 1} failed: ${e.message}")
|
|
||||||
if (delayMillis > 0) Thread.sleep(delayMillis)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw lastError ?: AssertionError("Test failed after $maxRetries attempts")
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2021 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
|
|
||||||
import org.kiwix.kiwixmobile.core.page.adapter.Page
|
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmark
|
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
|
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
|
||||||
|
|
||||||
internal class NewBookmarksDaoTest {
|
|
||||||
private val box: Box<BookmarkEntity> = mockk(relaxed = true)
|
|
||||||
private val newBookmarksDao = NewBookmarksDao(box)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deletePages() {
|
|
||||||
val bookmarkItem: BookmarkItem = bookmark(zimReaderSource = mockk())
|
|
||||||
val bookmarkItemList: List<BookmarkItem> = listOf(bookmarkItem)
|
|
||||||
val pagesToDelete: List<Page> = bookmarkItemList
|
|
||||||
newBookmarksDao.deletePages(pagesToDelete)
|
|
||||||
verify { newBookmarksDao.deleteBookmarks(bookmarkItemList) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getCurrentZimBookmarksUrl() {
|
|
||||||
val bookmarkItem: BookmarkItem = mockk(relaxed = true)
|
|
||||||
val zimFileReader: ZimFileReader? = mockk(relaxed = true)
|
|
||||||
val queryBuilder: QueryBuilder<BookmarkEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
BookmarkEntity_.zimId, "", QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.or() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
BookmarkEntity_.zimName, "", QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.order(BookmarkEntity_.bookmarkTitle) } returns queryBuilder
|
|
||||||
val query: Query<BookmarkEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every { bookmarkItem.zimId } returns ""
|
|
||||||
every { bookmarkItem.zimName } returns ""
|
|
||||||
every { bookmarkItem.databaseId } returns 0L
|
|
||||||
newBookmarksDao.getCurrentZimBookmarksUrl(zimFileReader)
|
|
||||||
every {
|
|
||||||
query.property(BookmarkEntity_.bookmarkUrl).findStrings().toList().distinct()
|
|
||||||
} returns listOf("")
|
|
||||||
verify { box.query() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun bookmarkUrlsForCurrentBook() {
|
|
||||||
val bookmarkItem: BookmarkItem = mockk(relaxed = true)
|
|
||||||
val zimFileReader: ZimFileReader? = mockk(relaxed = true)
|
|
||||||
val queryBuilder: QueryBuilder<BookmarkEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
BookmarkEntity_.zimId,
|
|
||||||
zimFileReader?.id ?: "", QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.or() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
BookmarkEntity_.zimName,
|
|
||||||
zimFileReader?.name ?: "", QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.order(BookmarkEntity_.bookmarkTitle) } returns queryBuilder
|
|
||||||
val query: Query<BookmarkEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every { bookmarkItem.zimId } returns ""
|
|
||||||
every { bookmarkItem.zimName } returns ""
|
|
||||||
every { bookmarkItem.databaseId } returns 0L
|
|
||||||
newBookmarksDao.bookmarkUrlsForCurrentBook(zimFileReader)
|
|
||||||
verify { box.query() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveBookmark() {
|
|
||||||
val bookmarkItem: BookmarkItem = bookmark(zimReaderSource = mockk())
|
|
||||||
newBookmarksDao.saveBookmark(bookmarkItem)
|
|
||||||
verify { box.put(BookmarkEntity(bookmarkItem)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deleteBookmark() {
|
|
||||||
val bookmarkUrl = "bookmarkUrl"
|
|
||||||
val queryBuilder: QueryBuilder<BookmarkEntity> = mockk(relaxed = true)
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
BookmarkEntity_.bookmarkUrl,
|
|
||||||
bookmarkUrl,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<BookmarkEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
newBookmarksDao.deleteBookmark(bookmarkUrl)
|
|
||||||
verify { query.remove() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2021 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import io.mockk.CapturingSlot
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.slot
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.LanguageEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.concurrent.Callable
|
|
||||||
|
|
||||||
internal class NewLanguagesDaoTest {
|
|
||||||
private val box: Box<LanguageEntity> = mockk(relaxed = true)
|
|
||||||
private val newLanguagesDao = NewLanguagesDao(box)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun insert() {
|
|
||||||
val id = 0L
|
|
||||||
val active = false
|
|
||||||
val occurrencesOfLanguage = 0
|
|
||||||
val language: Language = mockk()
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { box.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
every { language.id } returns id
|
|
||||||
every { language.active } returns active
|
|
||||||
every { language.languageCode } returns Locale.ENGLISH.toString()
|
|
||||||
every { language.occurencesOfLanguage } returns occurrencesOfLanguage
|
|
||||||
newLanguagesDao.insert(listOf(language))
|
|
||||||
slot.captured.call()
|
|
||||||
verify { box.removeAll() }
|
|
||||||
verify {
|
|
||||||
box.put(
|
|
||||||
listOf(
|
|
||||||
LanguageEntity(
|
|
||||||
id = 0L,
|
|
||||||
locale = Locale.ENGLISH,
|
|
||||||
active = false,
|
|
||||||
occurencesOfLanguage = 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2022 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.mockk.CapturingSlot
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.slot
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
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
|
|
||||||
|
|
||||||
internal class NewNoteDaoTest {
|
|
||||||
private val notesBox: Box<NotesEntity> = mockk(relaxed = true)
|
|
||||||
private val newNotesDao = NewNoteDao(notesBox)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deletePages() {
|
|
||||||
val notesItem: NoteListItem = note(zimReaderSource = mockk())
|
|
||||||
val notesItemList: List<NoteListItem> = listOf(notesItem)
|
|
||||||
val pagesToDelete: List<Page> = notesItemList
|
|
||||||
newNotesDao.deletePages(pagesToDelete)
|
|
||||||
verify { newNotesDao.deleteNotes(notesItemList) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun deleteNotePage() {
|
|
||||||
val noteTitle = "abNotesTitle"
|
|
||||||
val queryBuilder: QueryBuilder<NotesEntity> = mockk(relaxed = true)
|
|
||||||
every { notesBox.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
NotesEntity_.noteTitle,
|
|
||||||
noteTitle,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<NotesEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
newNotesDao.deleteNote(noteTitle)
|
|
||||||
verify { query.remove() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun saveNotePage() {
|
|
||||||
val newNote: NoteListItem = note(title = "", zimReaderSource = mockk())
|
|
||||||
val slot: CapturingSlot<Callable<Unit>> = slot()
|
|
||||||
every { notesBox.store.callInTx(capture(slot)) } returns Unit
|
|
||||||
val queryBuilder: QueryBuilder<NotesEntity> = mockk(relaxed = true)
|
|
||||||
every { notesBox.query() } returns queryBuilder
|
|
||||||
val query: Query<NotesEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
NotesEntity_.noteTitle,
|
|
||||||
newNote.title,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
newNotesDao.saveNote(newNote)
|
|
||||||
slot.captured.call()
|
|
||||||
verify { notesBox.put(NotesEntity(newNote)) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
|
||||||
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.verify
|
|
||||||
import io.objectbox.Box
|
|
||||||
import io.objectbox.query.Query
|
|
||||||
import io.objectbox.query.QueryBuilder
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.jupiter.api.Nested
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity
|
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity_
|
|
||||||
import org.kiwix.kiwixmobile.core.search.SearchListItem.RecentSearchListItem
|
|
||||||
import org.kiwix.kiwixmobile.core.search.viewmodel.test
|
|
||||||
import org.kiwix.sharedFunctions.recentSearchEntity
|
|
||||||
|
|
||||||
internal class NewRecentSearchDaoTest {
|
|
||||||
private val box: Box<RecentSearchEntity> = mockk(relaxed = true)
|
|
||||||
private val flowBuilder: FlowBuilder = mockk()
|
|
||||||
private val newRecentSearchDao = NewRecentSearchDao(box, flowBuilder)
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
inner class RecentSearchTests {
|
|
||||||
@Test
|
|
||||||
fun `recentSearches searches by Id passed`() =
|
|
||||||
runTest {
|
|
||||||
val zimId = "id"
|
|
||||||
val queryResult = listOf<RecentSearchEntity>(recentSearchEntity())
|
|
||||||
expectFromRecentSearches(queryResult, zimId)
|
|
||||||
newRecentSearchDao.recentSearches(zimId)
|
|
||||||
.test(this)
|
|
||||||
.assertValues(
|
|
||||||
mutableListOf(queryResult.map { RecentSearchListItem(it.searchTerm, it.url) })
|
|
||||||
)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `recentSearches searches with blank Id if null passed`() =
|
|
||||||
runTest {
|
|
||||||
val queryResult = listOf<RecentSearchEntity>(recentSearchEntity())
|
|
||||||
expectFromRecentSearches(queryResult, "")
|
|
||||||
newRecentSearchDao.recentSearches(null)
|
|
||||||
.test(this)
|
|
||||||
.assertValues(
|
|
||||||
mutableListOf(queryResult.map { RecentSearchListItem(it.searchTerm, it.url) })
|
|
||||||
)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `recentSearches searches returns distinct entities by searchTerm`() =
|
|
||||||
runTest {
|
|
||||||
val queryResult = listOf<RecentSearchEntity>(recentSearchEntity(), recentSearchEntity())
|
|
||||||
expectFromRecentSearches(queryResult, "")
|
|
||||||
newRecentSearchDao.recentSearches("")
|
|
||||||
.test(this)
|
|
||||||
.assertValues(
|
|
||||||
mutableListOf(queryResult.take(1).map { RecentSearchListItem(it.searchTerm, it.url) })
|
|
||||||
)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `recentSearches searches returns a limitedNumber of entities`() =
|
|
||||||
runTest {
|
|
||||||
val searchResults: List<RecentSearchEntity> =
|
|
||||||
(0..200).map { recentSearchEntity(searchTerm = "$it") }
|
|
||||||
expectFromRecentSearches(searchResults, "")
|
|
||||||
newRecentSearchDao.recentSearches("")
|
|
||||||
.test(this)
|
|
||||||
.assertLastValue { it.size == 100 }
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun expectFromRecentSearches(queryResult: List<RecentSearchEntity>, zimId: String) {
|
|
||||||
val queryBuilder = mockk<QueryBuilder<RecentSearchEntity>>()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
RecentSearchEntity_.zimId,
|
|
||||||
zimId,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
every { queryBuilder.orderDesc(RecentSearchEntity_.id) } returns queryBuilder
|
|
||||||
val query = mockk<Query<RecentSearchEntity>>()
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
every { flowBuilder.buildCallbackFlow(query) } returns flowOf(queryResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `saveSearch puts RecentSearchEntity into box`() {
|
|
||||||
newRecentSearchDao.saveSearch("title", "id", "https://kiwix.app/mainPage")
|
|
||||||
verify {
|
|
||||||
box.put(
|
|
||||||
recentSearchEntity(
|
|
||||||
searchTerm = "title",
|
|
||||||
zimId = "id",
|
|
||||||
url = "https://kiwix.app/mainPage"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `deleteSearchString removes query results for the term`() {
|
|
||||||
val searchTerm = "searchTerm"
|
|
||||||
val queryBuilder: QueryBuilder<RecentSearchEntity> = mockk()
|
|
||||||
every { box.query() } returns queryBuilder
|
|
||||||
every {
|
|
||||||
queryBuilder.equal(
|
|
||||||
RecentSearchEntity_.searchTerm,
|
|
||||||
searchTerm,
|
|
||||||
QueryBuilder.StringOrder.CASE_INSENSITIVE
|
|
||||||
)
|
|
||||||
} returns queryBuilder
|
|
||||||
val query: Query<RecentSearchEntity> = mockk(relaxed = true)
|
|
||||||
every { queryBuilder.build() } returns query
|
|
||||||
newRecentSearchDao.deleteSearchString(searchTerm)
|
|
||||||
verify { query.remove() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `deleteSearchHistory deletes everything`() {
|
|
||||||
newRecentSearchDao.deleteSearchHistory()
|
|
||||||
verify { box.removeAll() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmarkState
|
import org.kiwix.kiwixmobile.core.page.bookmarkState
|
||||||
import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem
|
import org.kiwix.kiwixmobile.core.page.libkiwixBookmarkItem
|
||||||
@ -41,7 +41,7 @@ import java.util.UUID
|
|||||||
|
|
||||||
internal class ShowDeleteBookmarksDialogTest {
|
internal class ShowDeleteBookmarksDialogTest {
|
||||||
val effects = mockk<MutableSharedFlow<SideEffect<*>>>(relaxed = true)
|
val effects = mockk<MutableSharedFlow<SideEffect<*>>>(relaxed = true)
|
||||||
private val newBookmarksDao = mockk<NewBookmarksDao>()
|
private val libkiwixBookmark = mockk<LibkiwixBookmarks>()
|
||||||
val activity = mockk<CoreMainActivity>()
|
val activity = mockk<CoreMainActivity>()
|
||||||
private val dialogShower = mockk<DialogShower>(relaxed = true)
|
private val dialogShower = mockk<DialogShower>(relaxed = true)
|
||||||
private val viewModelScope = CoroutineScope(Dispatchers.IO)
|
private val viewModelScope = CoroutineScope(Dispatchers.IO)
|
||||||
@ -52,7 +52,7 @@ internal class ShowDeleteBookmarksDialogTest {
|
|||||||
ShowDeleteBookmarksDialog(
|
ShowDeleteBookmarksDialog(
|
||||||
effects,
|
effects,
|
||||||
bookmarkState(),
|
bookmarkState(),
|
||||||
newBookmarksDao,
|
libkiwixBookmark,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
@ -61,7 +61,7 @@ internal class ShowDeleteBookmarksDialogTest {
|
|||||||
showDeleteBookmarksDialog.invokeWith(activity)
|
showDeleteBookmarksDialog.invokeWith(activity)
|
||||||
verify { dialogShower.show(any(), capture(lambdaSlot)) }
|
verify { dialogShower.show(any(), capture(lambdaSlot)) }
|
||||||
lambdaSlot.captured.invoke()
|
lambdaSlot.captured.invoke()
|
||||||
verify { effects.tryEmit(DeletePageItems(bookmarkState(), newBookmarksDao, viewModelScope)) }
|
verify { effects.tryEmit(DeletePageItems(bookmarkState(), libkiwixBookmark, viewModelScope)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mockkActivityInjection(showDeleteBookmarksDialog: ShowDeleteBookmarksDialog) {
|
private fun mockkActivityInjection(showDeleteBookmarksDialog: ShowDeleteBookmarksDialog) {
|
||||||
@ -88,7 +88,7 @@ internal class ShowDeleteBookmarksDialogTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
newBookmarksDao,
|
libkiwixBookmark,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
@ -113,7 +113,7 @@ internal class ShowDeleteBookmarksDialogTest {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
newBookmarksDao,
|
libkiwixBookmark,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.page.historyItem
|
import org.kiwix.kiwixmobile.core.page.historyItem
|
||||||
import org.kiwix.kiwixmobile.core.page.historyState
|
import org.kiwix.kiwixmobile.core.page.historyState
|
||||||
@ -21,7 +21,7 @@ import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.DeleteSelectedHistory
|
|||||||
|
|
||||||
internal class ShowDeleteHistoryDialogTest {
|
internal class ShowDeleteHistoryDialogTest {
|
||||||
val effects = mockk<MutableSharedFlow<SideEffect<*>>>(relaxed = true)
|
val effects = mockk<MutableSharedFlow<SideEffect<*>>>(relaxed = true)
|
||||||
private val historyDao = mockk<HistoryDao>()
|
private val historyRoomDao = mockk<HistoryRoomDao>()
|
||||||
val activity = mockk<CoreMainActivity>()
|
val activity = mockk<CoreMainActivity>()
|
||||||
private val dialogShower = mockk<DialogShower>(relaxed = true)
|
private val dialogShower = mockk<DialogShower>(relaxed = true)
|
||||||
private val viewModelScope = CoroutineScope(Dispatchers.IO)
|
private val viewModelScope = CoroutineScope(Dispatchers.IO)
|
||||||
@ -33,7 +33,7 @@ internal class ShowDeleteHistoryDialogTest {
|
|||||||
ShowDeleteHistoryDialog(
|
ShowDeleteHistoryDialog(
|
||||||
effects,
|
effects,
|
||||||
historyState(),
|
historyState(),
|
||||||
historyDao,
|
historyRoomDao,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
@ -42,7 +42,7 @@ internal class ShowDeleteHistoryDialogTest {
|
|||||||
showDeleteHistoryDialog.invokeWith(activity)
|
showDeleteHistoryDialog.invokeWith(activity)
|
||||||
verify { dialogShower.show(any(), capture(lambdaSlot)) }
|
verify { dialogShower.show(any(), capture(lambdaSlot)) }
|
||||||
lambdaSlot.captured.invoke()
|
lambdaSlot.captured.invoke()
|
||||||
verify { effects.tryEmit(DeletePageItems(historyState(), historyDao, viewModelScope)) }
|
verify { effects.tryEmit(DeletePageItems(historyState(), historyRoomDao, viewModelScope)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -52,7 +52,7 @@ internal class ShowDeleteHistoryDialogTest {
|
|||||||
ShowDeleteHistoryDialog(
|
ShowDeleteHistoryDialog(
|
||||||
effects,
|
effects,
|
||||||
historyState(listOf(historyItem(isSelected = true, zimReaderSource = mockk()))),
|
historyState(listOf(historyItem(isSelected = true, zimReaderSource = mockk()))),
|
||||||
historyDao,
|
historyRoomDao,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
@ -68,7 +68,7 @@ internal class ShowDeleteHistoryDialogTest {
|
|||||||
ShowDeleteHistoryDialog(
|
ShowDeleteHistoryDialog(
|
||||||
effects,
|
effects,
|
||||||
historyState(),
|
historyState(),
|
||||||
historyDao,
|
historyRoomDao,
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
dialogShower
|
dialogShower
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user