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