Fixed: Books are not displayed on the LocalLibrary screen if a book is deleted from storage after being added to the DAO.

* Improved the test cases as well.
This commit is contained in:
MohitMaliFtechiz 2024-12-05 18:46:54 +05:30 committed by Kelson
parent f78e1447a6
commit 3e47cfa6ae
4 changed files with 21 additions and 17 deletions

View File

@ -60,7 +60,7 @@ class LibkiwixBookmarks @Inject constructor(
manager: Manager, manager: Manager,
val sharedPreferenceUtil: SharedPreferenceUtil, val sharedPreferenceUtil: SharedPreferenceUtil,
private val bookDao: NewBookDao, private val bookDao: NewBookDao,
private val zimReaderContainer: ZimReaderContainer?, private val zimReaderContainer: ZimReaderContainer?
) : PageDao { ) : PageDao {
/** /**

View File

@ -22,7 +22,6 @@ import io.objectbox.kotlin.inValues
import io.objectbox.kotlin.query import io.objectbox.kotlin.query
import io.objectbox.query.QueryBuilder import io.objectbox.query.QueryBuilder
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -64,12 +63,12 @@ class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
.flatMapSingle { bookOnDiskEntity -> .flatMapSingle { bookOnDiskEntity ->
// Check if the zimReaderSource exists as a suspend function // Check if the zimReaderSource exists as a suspend function
rxSingle { bookOnDiskEntity.zimReaderSource.exists() } rxSingle { bookOnDiskEntity.zimReaderSource.exists() }
.flatMap { exists -> .map { exists ->
if (exists) io.reactivex.rxjava3.core.Single.just(bookOnDiskEntity) bookOnDiskEntity to exists
else io.reactivex.rxjava3.core.Single.never()
} }
.onErrorResumeNext { _: Throwable -> io.reactivex.rxjava3.core.Single.never() }
} }
.filter(Pair<BookOnDiskEntity, Boolean>::second)
.map(Pair<BookOnDiskEntity, Boolean>::first)
.toList() .toList()
.toFlowable() .toFlowable()
} }

View File

@ -27,9 +27,11 @@ import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import io.reactivex.Flowable import io.reactivex.Flowable
import io.reactivex.processors.PublishProcessor import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.runBlocking
import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.DarkModeConfig
import org.kiwix.kiwixmobile.core.DarkModeConfig.Mode.Companion.from import org.kiwix.kiwixmobile.core.DarkModeConfig.Mode.Companion.from
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.extensions.isFileExist
import java.io.File import java.io.File
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
@ -114,9 +116,10 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
putStoragePosition(0) putStoragePosition(0)
} }
!File(storage).exists() -> getPublicDirectoryPath(defaultPublicStorage()).also { runBlocking { !File(storage).isFileExist() } ->
putStoragePosition(0) getPublicDirectoryPath(defaultPublicStorage()).also {
} putStoragePosition(0)
}
else -> storage else -> storage
} }

View File

@ -32,6 +32,8 @@ import io.objectbox.query.Query
import io.objectbox.query.QueryBuilder import io.objectbox.query.QueryBuilder
import io.objectbox.rx.RxQuery import io.objectbox.rx.RxQuery
import io.reactivex.Observable import io.reactivex.Observable
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
@ -62,20 +64,20 @@ internal class NewBookDaoTest {
inner class BooksTests { inner class BooksTests {
@Test @Test
fun `books emits entities whose file exists`() { fun `books emits entities whose file exists`() {
val (expectedEntity, _) = expectEmissionOfExistingAndNotExistingBook() runBlocking {
val books = newBookDao.books().test().also { val (expectedEntity, _) = expectEmissionOfExistingAndNotExistingBook()
it.awaitTerminalEvent() val books = newBookDao.books().test()
delay(1000)
books.assertValues(listOf(BookOnDisk(expectedEntity)))
} }
books.assertValues(listOf(BookOnDisk(expectedEntity)))
} }
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
@Test @Test
fun `books deletes entities whose file does not exist`() { fun `books deletes entities whose file does not exist`() = runBlocking {
val (_, deletedEntity) = expectEmissionOfExistingAndNotExistingBook() val (_, deletedEntity) = expectEmissionOfExistingAndNotExistingBook()
newBookDao.books().test().also { newBookDao.books().test()
it.awaitTerminalEvent() delay(1000)
}
verify { box.remove(listOf(deletedEntity)) } verify { box.remove(listOf(deletedEntity)) }
} }