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 b1f2e655e..15a731837 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
@@ -31,7 +31,11 @@ import android.view.View.VISIBLE
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
+import androidx.lifecycle.lifecycleScope
import com.google.android.material.bottomnavigation.BottomNavigationView
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.cachedComponent
import org.kiwix.kiwixmobile.core.R.anim
@@ -219,23 +223,27 @@ class KiwixReaderFragment : CoreReaderFragment() {
) {
val settings = requireActivity().getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0)
val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null))
-
- if (zimReaderSource != null && zimReaderSource.canOpenInLibkiwix()) {
- if (zimReaderContainer?.zimReaderSource == null) {
- openZimFile(zimReaderSource)
- Log.d(
- TAG_KIWIX,
- "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}"
- )
- } else {
- zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
+ lifecycleScope.launch {
+ val canOpenInLibkiwix = withContext(Dispatchers.IO) {
+ zimReaderSource?.canOpenInLibkiwix()
}
- } else {
- getCurrentWebView()?.snack(string.zim_not_opened)
- exitBook() // hide the options for zim file to avoid unexpected UI behavior
- return // book not found so don't need to restore the tabs for this file
+ if (zimReaderSource != null && canOpenInLibkiwix == true) {
+ if (zimReaderContainer?.zimReaderSource == null) {
+ openZimFile(zimReaderSource)
+ Log.d(
+ TAG_KIWIX,
+ "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}"
+ )
+ } else {
+ zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
+ }
+ } else {
+ getCurrentWebView()?.snack(string.zim_not_opened)
+ exitBook() // hide the options for zim file to avoid unexpected UI behavior
+ return@launch // book not found so don't need to restore the tabs for this file
+ }
+ restoreTabs(zimArticles, zimPositions, currentTab)
}
- restoreTabs(zimArticles, zimPositions, currentTab)
}
@Throws(IllegalArgumentException::class)
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 43eb6aed8..5ecd169fc 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,16 @@
package org.kiwix.kiwixmobile.zimManager.fileselectView.effects
import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
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.toast
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
+import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader
data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.BookOnDisk) :
@@ -31,14 +36,19 @@ data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.Bo
override fun invokeWith(activity: AppCompatActivity) {
val zimReaderSource = bookOnDisk.zimReaderSource
- if (!zimReaderSource.canOpenInLibkiwix()) {
- activity.toast(R.string.error_file_not_found)
- } else {
- activity.navigate(
- actionNavigationLibraryToNavigationReader().apply {
- zimFileUri = zimReaderSource.toDatabase()
- }
- )
+ (activity as KiwixMainActivity).lifecycleScope.launch {
+ val canOpenInLibkiwix = withContext(Dispatchers.IO) {
+ zimReaderSource.canOpenInLibkiwix()
+ }
+ if (!canOpenInLibkiwix) {
+ activity.toast(R.string.error_file_not_found)
+ } else {
+ activity.navigate(
+ actionNavigationLibraryToNavigationReader().apply {
+ zimFileUri = zimReaderSource.toDatabase()
+ }
+ )
+ }
}
}
}
diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt
index 252ace60b..5633c803b 100644
--- a/buildSrc/src/main/kotlin/Libs.kt
+++ b/buildSrc/src/main/kotlin/Libs.kt
@@ -22,6 +22,9 @@ object Libs {
"org.jetbrains.kotlinx:kotlinx-coroutines-android:" +
Versions.org_jetbrains_kotlinx_kotlinx_coroutines
+ const val kotlinx_coroutines_rx3: String =
+ "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:" + Versions.kotlinx_coroutines_rx3
+
/**
* https://github.com/Kotlin/kotlinx.coroutines
*/
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 63b40eeca..aa59c8599 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -16,6 +16,8 @@ object Versions {
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.8.1"
+ const val kotlinx_coroutines_rx3: String = "1.3.9"
+
const val androidx_test_espresso: String = "3.5.1"
const val tracing: String = "1.1.0"
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index aeb3bec79..20216805f 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -61,5 +61,6 @@ dependencies {
implementation(Libs.webkit)
testImplementation(Libs.kotlinx_coroutines_test)
implementation(Libs.kotlinx_coroutines_android)
+ implementation(Libs.kotlinx_coroutines_rx3)
implementation(Libs.zxing)
}
diff --git a/core/detekt_baseline.xml b/core/detekt_baseline.xml
index af8150f87..552831001 100644
--- a/core/detekt_baseline.xml
+++ b/core/detekt_baseline.xml
@@ -12,7 +12,7 @@
LongParameterList:MainMenu.kt$MainMenu$( private val activity: Activity, zimFileReader: ZimFileReader?, menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, disableReadAloud: Boolean = false, disableTabs: Boolean = false, private val menuClickListener: MenuClickListener )
LongParameterList:MainMenu.kt$MainMenu.Factory$( menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, menuClickListener: MenuClickListener, disableReadAloud: Boolean, disableTabs: Boolean )
LongParameterList:PageTestHelpers.kt$( bookmarkTitle: String = "bookmarkTitle", isSelected: Boolean = false, id: Long = 2, zimId: String = "zimId", zimName: String = "zimName", zimFilePath: String = "zimFilePath", bookmarkUrl: String = "bookmarkUrl", favicon: String = "favicon" )
- LongParameterList:Repository.kt$Repository$( @param:IO private val io: Scheduler, @param:MainThread private val mainThread: Scheduler, private val bookDao: NewBookDao, private val bookmarksDao: NewBookmarksDao, private val historyDao: HistoryDao, private val languageDao: NewLanguagesDao, private val recentSearchDao: NewRecentSearchDao, private val zimReaderContainer: ZimReaderContainer )
+ LongParameterList:Repository.kt$Repository$( @param:IO private val ioThread: Scheduler, @param:MainThread private val mainThread: Scheduler, private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, private val zimReaderContainer: ZimReaderContainer )
LongParameterList:ToolbarScrollingKiwixWebView.kt$ToolbarScrollingKiwixWebView$( context: Context, callback: WebViewCallback, attrs: AttributeSet, nonVideoView: ViewGroup, videoView: ViewGroup, webViewClient: CoreWebViewClient, private val toolbarView: View, private val bottomBarView: View, sharedPreferenceUtil: SharedPreferenceUtil, private val parentNavigationBar: View? = null )
MagicNumber:ArticleCount.kt$ArticleCount$3
MagicNumber:CompatFindActionModeCallback.kt$CompatFindActionModeCallback$100
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 bd909712f..310f9ec29 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
@@ -29,10 +29,12 @@ import io.reactivex.subjects.BehaviorSubject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.rx3.rxSingle
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.DarkModeConfig
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
+import org.kiwix.kiwixmobile.core.extensions.deleteFile
import org.kiwix.kiwixmobile.core.extensions.isFileExist
import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.page.adapter.Page
@@ -68,8 +70,13 @@ class LibkiwixBookmarks @Inject constructor(
private var bookmarkList: List = arrayListOf()
private var libraryBooksList: List = arrayListOf()
+ @Suppress("CheckResult")
private val bookmarkListBehaviour: BehaviorSubject>? by lazy {
- BehaviorSubject.createDefault(getBookmarksList())
+ BehaviorSubject.create>().also { subject ->
+ rxSingle { getBookmarksList() }
+ .subscribeOn(io.reactivex.rxjava3.schedulers.Schedulers.io())
+ .subscribe(subject::onNext, subject::onError)
+ }
}
private val bookmarksFolderPath: String by lazy {
@@ -113,7 +120,7 @@ class LibkiwixBookmarks @Inject constructor(
override fun deletePages(pagesToDelete: List) =
deleteBookmarks(pagesToDelete as List)
- fun getCurrentZimBookmarksUrl(zimFileReader: ZimFileReader?): List {
+ suspend fun getCurrentZimBookmarksUrl(zimFileReader: ZimFileReader?): List {
return zimFileReader?.let { reader ->
getBookmarksList()
.filter { it.zimId == reader.id }
@@ -134,7 +141,7 @@ class LibkiwixBookmarks @Inject constructor(
* during data migration, where data is written to the file only once after all bookmarks
* have been added to libkiwix to optimize the process.
*/
- fun saveBookmark(
+ suspend fun saveBookmark(
libkiwixBookmarkItem: LibkiwixBookmarkItem,
shouldWriteBookmarkToFile: Boolean = true
) {
@@ -241,7 +248,7 @@ class LibkiwixBookmarks @Inject constructor(
}
@Suppress("ReturnCount")
- private fun getBookmarksList(): List {
+ private suspend fun getBookmarksList(): List {
if (!bookmarksChanged && bookmarkList.isNotEmpty()) {
// No changes, return the cached data
return bookmarkList.distinctBy(LibkiwixBookmarkItem::bookmarkUrl)
@@ -290,7 +297,7 @@ class LibkiwixBookmarks @Inject constructor(
}
@Suppress("NestedBlockDepth")
- private fun deleteDuplicateBookmarks() {
+ private suspend fun deleteDuplicateBookmarks() {
bookmarkList.groupBy { it.bookmarkUrl to it.zimReaderSource }
.filter { it.value.size > 1 }
.forEach { (_, value) ->
@@ -319,7 +326,7 @@ class LibkiwixBookmarks @Inject constructor(
}
}
- private fun getZimFileReaderFromBookmark(
+ private suspend fun getZimFileReaderFromBookmark(
bookmarkItem: LibkiwixBookmarkItem,
coreApp: CoreApp
): ZimFileReader? {
@@ -342,7 +349,7 @@ class LibkiwixBookmarks @Inject constructor(
}
}
- private fun isBookMarkExist(libkiwixBookmarkItem: LibkiwixBookmarkItem): Boolean =
+ private suspend fun isBookMarkExist(libkiwixBookmarkItem: LibkiwixBookmarkItem): Boolean =
getBookmarksList()
.any {
it.url == libkiwixBookmarkItem.bookmarkUrl &&
@@ -368,7 +375,11 @@ class LibkiwixBookmarks @Inject constructor(
}
private fun updateFlowableBookmarkList() {
- bookmarkListBehaviour?.onNext(getBookmarksList())
+ bookmarkListBehaviour?.let { subject ->
+ rxSingle { getBookmarksList() }
+ .subscribeOn(io.reactivex.rxjava3.schedulers.Schedulers.io())
+ .subscribe(subject::onNext, subject::onError)
+ }
}
// Export the `bookmark.xml` file to the `Download/org.kiwix/` directory of internal storage.
@@ -408,7 +419,7 @@ class LibkiwixBookmarks @Inject constructor(
}.first { !it.isFileExist() }
}
- fun importBookmarks(bookmarkFile: File) {
+ suspend fun importBookmarks(bookmarkFile: File) {
// Create a temporary library manager to import the bookmarks.
val tempLibrary = Library()
Manager(tempLibrary).apply {
@@ -426,7 +437,7 @@ class LibkiwixBookmarks @Inject constructor(
sharedPreferenceUtil.context.toast(R.string.bookmark_imported_message)
if (bookmarkFile.exists()) {
- bookmarkFile.delete()
+ bookmarkFile.deleteFile()
}
}
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 96fd19907..410848931 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
@@ -21,6 +21,7 @@ import io.objectbox.Box
import io.objectbox.kotlin.inValues
import io.objectbox.kotlin.query
import io.objectbox.query.QueryBuilder
+import kotlinx.coroutines.rx3.rxSingle
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
@@ -31,23 +32,29 @@ import javax.inject.Inject
class NewBookDao @Inject constructor(private val box: Box) {
fun books() = box.asFlowable()
- .map { books ->
- books.map { bookOnDiskEntity ->
- bookOnDiskEntity.file.let { file ->
- // set zimReaderSource for previously saved books
+ .flatMap { books ->
+ io.reactivex.rxjava3.core.Flowable.fromIterable(books)
+ .flatMapSingle { bookOnDiskEntity ->
+ val file = bookOnDiskEntity.file
val zimReaderSource = ZimReaderSource(file)
- if (zimReaderSource.canOpenInLibkiwix()) {
- bookOnDiskEntity.zimReaderSource = zimReaderSource
- }
+
+ rxSingle { zimReaderSource.canOpenInLibkiwix() }
+ .map { canOpen ->
+ if (canOpen) {
+ bookOnDiskEntity.zimReaderSource = zimReaderSource
+ }
+ bookOnDiskEntity
+ }
+ .onErrorReturn { bookOnDiskEntity }
}
- bookOnDiskEntity
- }
+ .toList()
+ .toFlowable()
}
.doOnNext { removeBooksThatDoNotExist(it.toMutableList()) }
.map { books -> books.filter { it.zimReaderSource.exists() } }
.map { it.map(::BookOnDisk) }
- fun getBooks() = box.all.map { bookOnDiskEntity ->
+ suspend fun getBooks() = box.all.map { bookOnDiskEntity ->
bookOnDiskEntity.file.let { file ->
// set zimReaderSource for previously saved books
val zimReaderSource = ZimReaderSource(file)
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt
index 290d07efb..0b897b039 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt
@@ -41,9 +41,11 @@ interface DataSource {
fun deleteHistory(historyList: List): Completable
fun clearHistory(): Completable
fun getBookmarks(): Flowable>
- fun getCurrentZimBookmarksUrl(): Single>
+ fun getCurrentZimBookmarksUrl(): io.reactivex.rxjava3.core.Single>
+
+ fun saveBookmark(libkiwixBookmarkItem: LibkiwixBookmarkItem):
+ io.reactivex.rxjava3.core.Completable
- fun saveBookmark(libkiwixBookmarkItem: LibkiwixBookmarkItem): Completable
fun deleteBookmarks(bookmarks: List): Completable
fun deleteBookmark(bookId: String, bookmarkUrl: String): Completable?
fun booksOnDiskAsListItems(): Flowable>
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt
index bca9ca611..de4c7884d 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt
@@ -21,7 +21,8 @@ package org.kiwix.kiwixmobile.core.data
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Scheduler
-import io.reactivex.Single
+import kotlinx.coroutines.rx3.rxCompletable
+import kotlinx.coroutines.rx3.rxSingle
import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
import org.kiwix.kiwixmobile.core.dao.NewBookDao
@@ -47,10 +48,9 @@ import javax.inject.Singleton
* A central repository of data which should provide the presenters with the required data.
*/
-@Suppress("LongParameterList")
@Singleton
class Repository @Inject internal constructor(
- @param:IO private val io: Scheduler,
+ @param:IO private val ioThread: Scheduler,
@param:MainThread private val mainThread: Scheduler,
private val bookDao: NewBookDao,
private val libkiwixBookmarks: LibkiwixBookmarks,
@@ -64,7 +64,7 @@ class Repository @Inject internal constructor(
override fun getLanguageCategorizedBooks() =
booksOnDiskAsListItems()
.first(emptyList())
- .subscribeOn(io)
+ .subscribeOn(ioThread)
.observeOn(mainThread)
override fun booksOnDiskAsListItems(): Flowable> = bookDao.books()
@@ -91,60 +91,60 @@ class Repository @Inject internal constructor(
override fun saveBooks(books: List) =
Completable.fromAction { bookDao.insert(books) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun saveBook(book: BookOnDisk) =
Completable.fromAction { bookDao.insert(listOf(book)) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun saveLanguages(languages: List) =
Completable.fromAction { languageDao.insert(languages) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun saveHistory(history: HistoryItem) =
Completable.fromAction { historyRoomDao.saveHistory(history) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun deleteHistory(historyList: List) =
Completable.fromAction {
historyRoomDao.deleteHistory(historyList.filterIsInstance(HistoryItem::class.java))
}
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun clearHistory() = Completable.fromAction {
historyRoomDao.deleteAllHistory()
recentSearchRoomDao.deleteSearchHistory()
- }.subscribeOn(io)
+ }.subscribeOn(ioThread)
override fun getBookmarks() =
libkiwixBookmarks.bookmarks() as Flowable>
override fun getCurrentZimBookmarksUrl() =
- Single.just(libkiwixBookmarks.getCurrentZimBookmarksUrl(zimReaderContainer.zimFileReader))
- .subscribeOn(io)
- .observeOn(mainThread)
+ rxSingle {
+ libkiwixBookmarks.getCurrentZimBookmarksUrl(zimReaderContainer.zimFileReader)
+ }.subscribeOn(io.reactivex.rxjava3.schedulers.Schedulers.io())
override fun saveBookmark(libkiwixBookmarkItem: LibkiwixBookmarkItem) =
- Completable.fromAction { libkiwixBookmarks.saveBookmark(libkiwixBookmarkItem) }
- .subscribeOn(io)
+ rxCompletable { libkiwixBookmarks.saveBookmark(libkiwixBookmarkItem) }
+ .subscribeOn(io.reactivex.rxjava3.schedulers.Schedulers.io())
override fun deleteBookmarks(bookmarks: List) =
Completable.fromAction { libkiwixBookmarks.deleteBookmarks(bookmarks) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun deleteBookmark(bookId: String, bookmarkUrl: String): Completable? =
Completable.fromAction { libkiwixBookmarks.deleteBookmark(bookId, bookmarkUrl) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun saveNote(noteListItem: NoteListItem): Completable =
Completable.fromAction { notesRoomDao.saveNote(noteListItem) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun deleteNotes(noteList: List) =
Completable.fromAction { notesRoomDao.deleteNotes(noteList) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
override fun deleteNote(noteTitle: String): Completable =
Completable.fromAction { notesRoomDao.deleteNote(noteTitle) }
- .subscribeOn(io)
+ .subscribeOn(ioThread)
}
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 f1002a074..80c240459 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
@@ -25,6 +25,8 @@ import android.os.Process
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.CoreApp.Companion.coreComponent
import org.kiwix.kiwixmobile.core.base.BaseActivity
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
@@ -87,7 +89,9 @@ open class ErrorActivity : BaseActivity() {
private fun setupReportButton() {
activityKiwixErrorBinding?.reportButton?.setOnClickListener {
- sendEmailLauncher.launch(Intent.createChooser(emailIntent(), "Send email..."))
+ lifecycleScope.launch {
+ sendEmailLauncher.launch(Intent.createChooser(emailIntent(), "Send email..."))
+ }
}
}
@@ -96,7 +100,7 @@ open class ErrorActivity : BaseActivity() {
restartApp()
}
- private fun emailIntent(): Intent {
+ private suspend fun emailIntent(): Intent {
val emailBody = buildBody()
return Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
@@ -122,7 +126,7 @@ open class ErrorActivity : BaseActivity() {
}
}
- private fun buildBody(): String = """
+ private suspend fun buildBody(): String = """
$initialBody
${if (activityKiwixErrorBinding?.allowCrash?.isChecked == true && exception != null) exceptionDetails() else ""}
@@ -139,7 +143,7 @@ open class ErrorActivity : BaseActivity() {
${exception?.let(::toStackTraceString)}
""".trimIndent()
- private fun zimFiles(): String {
+ private suspend fun zimFiles(): String {
val allZimFiles = bookDao.getBooks().joinToString {
"""
${it.book.title}:
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/FileExtensions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/FileExtensions.kt
index a405c4a30..95c733ded 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/FileExtensions.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/FileExtensions.kt
@@ -41,10 +41,6 @@ fun File.totalSpace(): Long = runBlocking {
}
}
-fun File.canReadFile(): Boolean = runBlocking {
- withContext(Dispatchers.IO) {
- canRead()
- }
-}
+suspend fun File.canReadFile(): Boolean = withContext(Dispatchers.IO) { canRead() }
suspend fun File.deleteFile(): Boolean = withContext(Dispatchers.IO) { delete() }
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 6bf336600..d9cf414de 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
@@ -80,6 +80,7 @@ import androidx.core.widget.ContentLoadingProgressBar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
+import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@@ -93,6 +94,9 @@ import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.processors.BehaviorProcessor
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONException
import org.kiwix.kiwixmobile.core.BuildConfig
@@ -1641,16 +1645,21 @@ abstract class CoreReaderFragment :
fun openZimFile(zimReaderSource: ZimReaderSource, isCustomApp: Boolean = false) {
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) || isCustomApp) {
- if (zimReaderSource.canOpenInLibkiwix()) {
- // Show content if there is `Open Library` button showing
- // and we are opening the ZIM file
- reopenBook()
- openAndSetInContainer(zimReaderSource)
- updateTitle()
- } else {
- exitBook()
- Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + zimReaderSource.toDatabase())
- requireActivity().toast(R.string.error_file_not_found, Toast.LENGTH_LONG)
+ lifecycleScope.launch {
+ val canOpenInLibkiwix = withContext(Dispatchers.IO) {
+ zimReaderSource.canOpenInLibkiwix()
+ }
+ if (canOpenInLibkiwix) {
+ // Show content if there is `Open Library` button showing
+ // and we are opening the ZIM file
+ reopenBook()
+ openAndSetInContainer(zimReaderSource)
+ updateTitle()
+ } else {
+ exitBook()
+ 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.zimReaderSource = zimReaderSource
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt
index 0198c9fb5..5557c2b23 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt
@@ -17,13 +17,13 @@
*/
package org.kiwix.kiwixmobile.core.main
-import org.kiwix.kiwixmobile.core.utils.files.Log
import io.reactivex.disposables.Disposable
import org.kiwix.kiwixmobile.core.data.DataSource
import org.kiwix.kiwixmobile.core.di.ActivityScope
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
+import org.kiwix.kiwixmobile.core.utils.files.Log
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import javax.inject.Inject
@@ -32,7 +32,7 @@ private const val TAG = "MainPresenter"
@ActivityScope
class MainRepositoryActions @Inject constructor(private val dataSource: DataSource) {
private var saveHistoryDisposable: Disposable? = null
- private var saveBookmarkDisposable: Disposable? = null
+ private var saveBookmarkDisposable: io.reactivex.rxjava3.disposables.Disposable? = null
private var saveNoteDisposable: Disposable? = null
private var saveBookDisposable: Disposable? = null
private var deleteNoteDisposable: Disposable? = null
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 f52a80e9f..dc0ff40ad 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
@@ -62,7 +62,7 @@ class ZimReaderSource(
}
}
- fun canOpenInLibkiwix(): Boolean {
+ suspend fun canOpenInLibkiwix(): Boolean {
return when {
file?.canReadFile() == true -> true
assetFileDescriptorList?.get(0)?.parcelFileDescriptor?.fd
@@ -72,7 +72,7 @@ class ZimReaderSource(
}
}
- fun createArchive(): Archive? {
+ suspend fun createArchive(): Archive? {
if (canOpenInLibkiwix()) {
return when {
file != null -> Archive(file.canonicalPath)
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/settings/CorePrefsFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/settings/CorePrefsFragment.kt
index e1f16f5d3..65638c765 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/settings/CorePrefsFragment.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/settings/CorePrefsFragment.kt
@@ -40,6 +40,9 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar
import eu.mhutti1.utils.storage.StorageDevice
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.CoreApp.Companion.coreComponent
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
import org.kiwix.kiwixmobile.core.DarkModeConfig
@@ -403,7 +406,9 @@ abstract class CorePrefsFragment :
createTempFile(contentResolver.openInputStream(uri)).apply {
if (isValidXmlFile(this)) {
- libkiwixBookmarks?.importBookmarks(this)
+ CoroutineScope(Dispatchers.IO).launch {
+ libkiwixBookmarks?.importBookmarks(this@apply)
+ }
} else {
activity.toast(
resources.getString(R.string.error_invalid_bookmark_file),
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/DonationDialogHandler.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/DonationDialogHandler.kt
index 75e0dec31..8a03593f8 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/DonationDialogHandler.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/DonationDialogHandler.kt
@@ -19,8 +19,11 @@
package org.kiwix.kiwixmobile.core.utils
import android.app.Activity
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
+import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import javax.inject.Inject
const val THREE_DAYS_IN_MILLISECONDS = 3 * 24 * 60 * 60 * 1000L
@@ -42,15 +45,19 @@ class DonationDialogHandler @Inject constructor(
val currentMilliSeconds = System.currentTimeMillis()
val lastPopupMillis = sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds
val timeDifference = currentMilliSeconds - lastPopupMillis
- if (shouldShowInitialPopup(lastPopupMillis) || timeDifference >= THREE_MONTHS_IN_MILLISECONDS) {
- if (isZimFilesAvailableInLibrary() && isTimeToShowDonation(currentMilliSeconds)) {
- showDonationDialogCallback?.showDonationDialog()
- resetDonateLater()
+ (activity as CoreMainActivity).lifecycleScope.launch {
+ if (shouldShowInitialPopup(lastPopupMillis) ||
+ timeDifference >= THREE_MONTHS_IN_MILLISECONDS
+ ) {
+ if (isZimFilesAvailableInLibrary() && isTimeToShowDonation(currentMilliSeconds)) {
+ showDonationDialogCallback?.showDonationDialog()
+ resetDonateLater()
+ }
}
}
}
- private fun shouldShowInitialPopup(lastPopupMillis: Long): Boolean =
+ private suspend fun shouldShowInitialPopup(lastPopupMillis: Long): Boolean =
lastPopupMillis == 0L && isZimFilesAvailableInLibrary()
private fun isTimeToShowDonation(currentMillis: Long): Boolean =
@@ -63,7 +70,7 @@ class DonationDialogHandler @Inject constructor(
return timeDifference >= THREE_DAYS_IN_MILLISECONDS
}
- fun isZimFilesAvailableInLibrary(): Boolean =
+ suspend fun isZimFilesAvailableInLibrary(): Boolean =
if (activity.isCustomApp()) true else newBookDao.getBooks().isNotEmpty()
fun updateLastDonationPopupShownTime() {
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/RateDialogHandler.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/RateDialogHandler.kt
index 0f1cf3666..70c68a342 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/RateDialogHandler.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/RateDialogHandler.kt
@@ -22,11 +22,14 @@ import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import androidx.annotation.IdRes
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.BuildConfig
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.di.ActivityScope
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
+import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.utils.NetworkUtils
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject
@@ -67,18 +70,20 @@ class RateDialogHandler @Inject constructor(
tempVisitCount = visitCounterPref?.count ?: 0
++tempVisitCount
visitCounterPref?.count = tempVisitCount
- if (shouldShowRateDialog() && NetworkUtils.isNetworkAvailable(activity)) {
- showRateDialog(iconResId)
+ (activity as CoreMainActivity).lifecycleScope.launch {
+ if (shouldShowRateDialog() && NetworkUtils.isNetworkAvailable(activity)) {
+ showRateDialog(iconResId)
+ }
}
}
- private fun shouldShowRateDialog(): Boolean {
+ private suspend fun shouldShowRateDialog(): Boolean {
return tempVisitCount >= VISITS_REQUIRED_TO_SHOW_RATE_DIALOG &&
visitCounterPref?.noThanksState == false && isTwoWeekPassed() &&
isZimFilesAvailableInLibrary() && !BuildConfig.DEBUG
}
- private fun isZimFilesAvailableInLibrary(): Boolean {
+ private suspend fun isZimFilesAvailableInLibrary(): Boolean {
// If it is a custom app, return true since custom apps always have the ZIM file.
if (activity.isCustomApp()) return true
// For Kiwix app, check if there are ZIM files available in the library.