mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-14 01:48:47 -04:00
Merge pull request #3724 from kiwix/Fix#822
Added the 'Export bookmarks' feature.
This commit is contained in:
commit
1b255d56dd
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2024 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.page.bookmarks
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.test.core.app.ActivityScenario
|
||||||
|
import androidx.test.espresso.accessibility.AccessibilityChecks
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.uiautomator.UiDevice
|
||||||
|
import io.objectbox.BoxStore
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.kiwix.kiwixmobile.BaseActivityTest
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
||||||
|
import org.kiwix.kiwixmobile.core.di.modules.DatabaseModule
|
||||||
|
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||||
|
import org.kiwix.kiwixmobile.testutils.RetryRule
|
||||||
|
import org.kiwix.kiwixmobile.testutils.TestUtils
|
||||||
|
import org.kiwix.libkiwix.Library
|
||||||
|
import org.kiwix.libkiwix.Manager
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ImportBookmarkTest : BaseActivityTest() {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
var retryRule = RetryRule()
|
||||||
|
|
||||||
|
private val boxStore: BoxStore? = DatabaseModule.boxStore
|
||||||
|
private val library = Library()
|
||||||
|
private val manager = Manager(library)
|
||||||
|
private val newBookDao = NewBookDao(boxStore!!.boxFor(BookOnDiskEntity::class.java))
|
||||||
|
lateinit var libkiwixBookmarks: LibkiwixBookmarks
|
||||||
|
|
||||||
|
private val bookmarkXmlData = """
|
||||||
|
<bookmarks>
|
||||||
|
<bookmark>
|
||||||
|
<book>
|
||||||
|
<id>1f88ab6f-c265-b3ff-8f49-b7f442950380</id>
|
||||||
|
<title>Alpine Linux Wiki</title>
|
||||||
|
<name>alpinelinux_en_all</name>
|
||||||
|
<flavour>maxi</flavour>
|
||||||
|
<language>eng</language>
|
||||||
|
<date>2023-01-18</date>
|
||||||
|
</book>
|
||||||
|
<title>Main Page</title>
|
||||||
|
<url>https://kiwix.app/A/Main_Page</url>
|
||||||
|
</bookmark>
|
||||||
|
<bookmark>
|
||||||
|
<book>
|
||||||
|
<id>1f88ab6f-c265-b3ff-8f49-b7f442950380</id>
|
||||||
|
<title>Alpine Linux Wiki</title>
|
||||||
|
<name>alpinelinux_en_all</name>
|
||||||
|
<flavour>maxi</flavour>
|
||||||
|
<language>eng</language>
|
||||||
|
<date>2023-01-18</date>
|
||||||
|
</book>
|
||||||
|
<title>Installation</title>
|
||||||
|
<url>https://kiwix.app/A/Installation</url>
|
||||||
|
</bookmark>
|
||||||
|
<bookmark>
|
||||||
|
<book>
|
||||||
|
<id>04bf4329-9bfb-3681-03e2-cfae7b047f24</id>
|
||||||
|
<title>Ray Charles</title>
|
||||||
|
<name>wikipedia_en_ray_charles</name>
|
||||||
|
<flavour>maxi</flavour>
|
||||||
|
<language>eng</language>
|
||||||
|
<date>2024-03-17</date>
|
||||||
|
</book>
|
||||||
|
<title>Wikipedia</title>
|
||||||
|
<url>https://kiwix.app/A/index</url>
|
||||||
|
</bookmark>
|
||||||
|
</bookmarks>
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
override fun waitForIdle() {
|
||||||
|
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply {
|
||||||
|
if (TestUtils.isSystemUINotRespondingDialogVisible(this)) {
|
||||||
|
TestUtils.closeSystemDialogs(context, this)
|
||||||
|
}
|
||||||
|
waitForIdle()
|
||||||
|
}
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context).edit {
|
||||||
|
putBoolean(SharedPreferenceUtil.PREF_SHOW_INTRO, false)
|
||||||
|
putBoolean(SharedPreferenceUtil.PREF_WIFI_ONLY, false)
|
||||||
|
putBoolean(SharedPreferenceUtil.PREF_IS_TEST, true)
|
||||||
|
putBoolean(SharedPreferenceUtil.PREF_PLAY_STORE_RESTRICTION, false)
|
||||||
|
putString(SharedPreferenceUtil.PREF_LANG, "en")
|
||||||
|
}
|
||||||
|
activityScenario = ActivityScenario.launch(KiwixMainActivity::class.java).apply {
|
||||||
|
moveToState(Lifecycle.State.RESUMED)
|
||||||
|
onActivity {
|
||||||
|
LanguageUtils.handleLocaleChange(
|
||||||
|
it,
|
||||||
|
"en",
|
||||||
|
SharedPreferenceUtil(context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libkiwixBookmarks =
|
||||||
|
LibkiwixBookmarks(library, manager, SharedPreferenceUtil(context), newBookDao)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
AccessibilityChecks.enable().setRunChecksFromRootView(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun importBookmark() = runBlocking {
|
||||||
|
// clear the bookmarks to perform tes case properly.
|
||||||
|
clearBookmarks()
|
||||||
|
// test with empty data file
|
||||||
|
var tempBookmarkFile = getTemporaryBookmarkFile(true)
|
||||||
|
importBookmarks(tempBookmarkFile)
|
||||||
|
var actualDataAfterImporting = libkiwixBookmarks.bookmarks().blockingFirst()
|
||||||
|
assertEquals(0, actualDataAfterImporting.size)
|
||||||
|
|
||||||
|
// import the bookmark
|
||||||
|
tempBookmarkFile = getTemporaryBookmarkFile()
|
||||||
|
importBookmarks(tempBookmarkFile)
|
||||||
|
actualDataAfterImporting = libkiwixBookmarks.bookmarks().blockingFirst()
|
||||||
|
assertEquals(3, actualDataAfterImporting.size)
|
||||||
|
assertEquals(actualDataAfterImporting[0].title, "Main Page")
|
||||||
|
assertEquals(actualDataAfterImporting[0].url, "https://kiwix.app/A/Main_Page")
|
||||||
|
assertEquals(actualDataAfterImporting[0].zimId, "1f88ab6f-c265-b3ff-8f49-b7f442950380")
|
||||||
|
|
||||||
|
// import duplicate bookmarks
|
||||||
|
importBookmarks(tempBookmarkFile)
|
||||||
|
actualDataAfterImporting = libkiwixBookmarks.bookmarks().blockingFirst()
|
||||||
|
assertEquals(3, actualDataAfterImporting.size)
|
||||||
|
|
||||||
|
// delete the temp file
|
||||||
|
if (tempBookmarkFile.exists()) tempBookmarkFile.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun importBookmarks(tempBookmarkFile: File) {
|
||||||
|
activityScenario.onActivity {
|
||||||
|
runBlocking {
|
||||||
|
libkiwixBookmarks.importBookmarks(tempBookmarkFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearBookmarks() {
|
||||||
|
// delete bookmarks for testing other edge cases
|
||||||
|
libkiwixBookmarks.deleteBookmarks(
|
||||||
|
libkiwixBookmarks.bookmarks()
|
||||||
|
.blockingFirst() as List<LibkiwixBookmarkItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTemporaryBookmarkFile(isWithEmptyData: Boolean = false): File =
|
||||||
|
File(context.externalCacheDir, "bookmark.xml").apply {
|
||||||
|
createNewFile()
|
||||||
|
if (exists()) delete()
|
||||||
|
|
||||||
|
if (!isWithEmptyData) {
|
||||||
|
// Write the XML data to the temp file
|
||||||
|
writeText(bookmarkXmlData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -107,6 +107,12 @@ class KiwixSettingsFragmentTest {
|
|||||||
clickClearHistoryPreference()
|
clickClearHistoryPreference()
|
||||||
assertHistoryDialogDisplayed()
|
assertHistoryDialogDisplayed()
|
||||||
dismissDialog()
|
dismissDialog()
|
||||||
|
clickExportBookmarkPreference()
|
||||||
|
assertExportBookmarkDialogDisplayed()
|
||||||
|
dismissDialog()
|
||||||
|
clickOnImportBookmarkPreference()
|
||||||
|
assertImportBookmarkDialogDisplayed()
|
||||||
|
dismissDialog()
|
||||||
clickNightModePreference()
|
clickNightModePreference()
|
||||||
assertNightModeDialogDisplayed()
|
assertNightModeDialogDisplayed()
|
||||||
dismissDialog()
|
dismissDialog()
|
||||||
|
@ -116,6 +116,22 @@ class SettingsRobot : BaseRobot() {
|
|||||||
isVisible(TextId(R.string.clear_all_history_dialog_title))
|
isVisible(TextId(R.string.clear_all_history_dialog_title))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun clickExportBookmarkPreference() {
|
||||||
|
clickRecyclerViewItems(R.string.pref_export_bookmark_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertExportBookmarkDialogDisplayed() {
|
||||||
|
isVisible(TextId(R.string.export_all_bookmarks_dialog_title))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clickOnImportBookmarkPreference() {
|
||||||
|
clickRecyclerViewItems(R.string.pref_import_bookmark_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertImportBookmarkDialogDisplayed() {
|
||||||
|
isVisible(TextId(R.string.import_bookmarks_dialog_title))
|
||||||
|
}
|
||||||
|
|
||||||
fun clickNightModePreference() {
|
fun clickNightModePreference() {
|
||||||
clickRecyclerViewItems(R.string.pref_night_mode)
|
clickRecyclerViewItems(R.string.pref_night_mode)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import io.reactivex.functions.BiFunction
|
|||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
|
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileSearch
|
import org.kiwix.kiwixmobile.core.utils.files.FileSearch
|
||||||
@ -34,7 +35,8 @@ import javax.inject.Inject
|
|||||||
class StorageObserver @Inject constructor(
|
class StorageObserver @Inject constructor(
|
||||||
private val downloadDao: FetchDownloadDao,
|
private val downloadDao: FetchDownloadDao,
|
||||||
private val fileSearch: FileSearch,
|
private val fileSearch: FileSearch,
|
||||||
private val zimReaderFactory: ZimFileReader.Factory
|
private val zimReaderFactory: ZimFileReader.Factory,
|
||||||
|
private val libkiwixBookmarks: LibkiwixBookmarks
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun getBooksOnFileSystem(
|
fun getBooksOnFileSystem(
|
||||||
@ -56,6 +58,12 @@ class StorageObserver @Inject constructor(
|
|||||||
|
|
||||||
private fun convertToBookOnDisk(file: File) = runBlocking {
|
private fun convertToBookOnDisk(file: File) = runBlocking {
|
||||||
zimReaderFactory.create(file)
|
zimReaderFactory.create(file)
|
||||||
?.let { zimFileReader -> BookOnDisk(file, zimFileReader).also { zimFileReader.dispose() } }
|
?.let { zimFileReader ->
|
||||||
|
BookOnDisk(file, zimFileReader).also {
|
||||||
|
// add the book to libkiwix library to validate the imported bookmarks
|
||||||
|
libkiwixBookmarks.addBookToLibrary(archive = zimFileReader.jniKiwixReader)
|
||||||
|
zimFileReader.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
package org.kiwix.kiwixmobile.core.dao
|
package org.kiwix.kiwixmobile.core.dao
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.Log
|
|
||||||
import io.reactivex.BackpressureStrategy
|
import io.reactivex.BackpressureStrategy
|
||||||
import io.reactivex.BackpressureStrategy.LATEST
|
import io.reactivex.BackpressureStrategy.LATEST
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
@ -29,23 +29,28 @@ 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 org.kiwix.kiwixmobile.core.R
|
||||||
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.page.adapter.Page
|
import org.kiwix.kiwixmobile.core.page.adapter.Page
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||||
import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE
|
import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.files.Log
|
||||||
import org.kiwix.libkiwix.Book
|
import org.kiwix.libkiwix.Book
|
||||||
import org.kiwix.libkiwix.Bookmark
|
import org.kiwix.libkiwix.Bookmark
|
||||||
import org.kiwix.libkiwix.Library
|
import org.kiwix.libkiwix.Library
|
||||||
import org.kiwix.libkiwix.Manager
|
import org.kiwix.libkiwix.Manager
|
||||||
|
import org.kiwix.libzim.Archive
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LibkiwixBookmarks @Inject constructor(
|
class LibkiwixBookmarks @Inject constructor(
|
||||||
val library: Library,
|
val library: Library,
|
||||||
manager: Manager,
|
manager: Manager,
|
||||||
val sharedPreferenceUtil: SharedPreferenceUtil
|
val sharedPreferenceUtil: SharedPreferenceUtil,
|
||||||
|
private val bookDao: NewBookDao
|
||||||
) : PageDao {
|
) : PageDao {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,7 +137,13 @@ class LibkiwixBookmarks @Inject constructor(
|
|||||||
bookId = libkiwixBookmarkItem.zimId
|
bookId = libkiwixBookmarkItem.zimId
|
||||||
title = libkiwixBookmarkItem.title
|
title = libkiwixBookmarkItem.title
|
||||||
url = libkiwixBookmarkItem.url
|
url = libkiwixBookmarkItem.url
|
||||||
bookTitle = libkiwixBookmarkItem.libKiwixBook?.title ?: libkiwixBookmarkItem.zimId
|
bookTitle = when {
|
||||||
|
libkiwixBookmarkItem.libKiwixBook?.title != null ->
|
||||||
|
libkiwixBookmarkItem.libKiwixBook.title
|
||||||
|
|
||||||
|
libkiwixBookmarkItem.zimName.isNotBlank() -> libkiwixBookmarkItem.zimName
|
||||||
|
else -> libkiwixBookmarkItem.zimId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
library.addBookmark(bookmark).also {
|
library.addBookmark(bookmark).also {
|
||||||
if (shouldWriteBookmarkToFile) {
|
if (shouldWriteBookmarkToFile) {
|
||||||
@ -145,6 +156,26 @@ class LibkiwixBookmarks @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addBookToLibrary(file: File? = null, archive: Archive? = null) {
|
||||||
|
try {
|
||||||
|
bookmarksChanged = true
|
||||||
|
val book = Book().apply {
|
||||||
|
archive?.let {
|
||||||
|
update(archive)
|
||||||
|
} ?: run {
|
||||||
|
update(Archive(file?.canonicalPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addBookToLibraryIfNotExist(book)
|
||||||
|
updateFlowableBookmarkList()
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Error: Couldn't add the book to library.\nOriginal exception = $ignore"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun addBookToLibraryIfNotExist(libKiwixBook: Book?) {
|
private fun addBookToLibraryIfNotExist(libKiwixBook: Book?) {
|
||||||
libKiwixBook?.let { book ->
|
libKiwixBook?.let { book ->
|
||||||
if (!isBookAlreadyExistInLibrary(book.id)) {
|
if (!isBookAlreadyExistInLibrary(book.id)) {
|
||||||
@ -209,7 +240,9 @@ class LibkiwixBookmarks @Inject constructor(
|
|||||||
return bookmarkList
|
return bookmarkList
|
||||||
}
|
}
|
||||||
// Retrieve the list of bookmarks from the library, or return an empty list if it's null.
|
// Retrieve the list of bookmarks from the library, or return an empty list if it's null.
|
||||||
val bookmarkArray = library.getBookmarks(false)?.toList() ?: return bookmarkList
|
val bookmarkArray =
|
||||||
|
library.getBookmarks(false)?.toList()
|
||||||
|
?: return bookmarkList.distinctBy(LibkiwixBookmarkItem::bookmarkUrl)
|
||||||
|
|
||||||
// Create a list to store LibkiwixBookmarkItem objects.
|
// Create a list to store LibkiwixBookmarkItem objects.
|
||||||
bookmarkList = bookmarkArray.mapNotNull { bookmark ->
|
bookmarkList = bookmarkArray.mapNotNull { bookmark ->
|
||||||
@ -241,7 +274,21 @@ class LibkiwixBookmarks @Inject constructor(
|
|||||||
bookmarksChanged = false
|
bookmarksChanged = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bookmarkList
|
|
||||||
|
// Delete duplicates bookmarks if any exist
|
||||||
|
deleteDuplicateBookmarks()
|
||||||
|
|
||||||
|
return bookmarkList.distinctBy(LibkiwixBookmarkItem::bookmarkUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteDuplicateBookmarks() {
|
||||||
|
bookmarkList.groupBy { it.bookmarkUrl to it.zimFilePath }
|
||||||
|
.filter { it.value.size > 1 }
|
||||||
|
.forEach { (_, value) ->
|
||||||
|
value.drop(1).forEach { bookmarkItem ->
|
||||||
|
deleteBookmark(bookmarkItem.zimId, bookmarkItem.bookmarkUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isBookMarkExist(libkiwixBookmarkItem: LibkiwixBookmarkItem): Boolean =
|
private fun isBookMarkExist(libkiwixBookmarkItem: LibkiwixBookmarkItem): Boolean =
|
||||||
@ -273,6 +320,65 @@ class LibkiwixBookmarks @Inject constructor(
|
|||||||
bookmarkListBehaviour?.onNext(getBookmarksList())
|
bookmarkListBehaviour?.onNext(getBookmarksList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export the `bookmark.xml` file to the `Download/org.kiwix/` directory of internal storage.
|
||||||
|
fun exportBookmark() {
|
||||||
|
try {
|
||||||
|
val bookmarkDestinationFile = exportedFile("bookmark.xml")
|
||||||
|
bookmarkFile.inputStream().use { inputStream ->
|
||||||
|
bookmarkDestinationFile.outputStream().use(inputStream::copyTo)
|
||||||
|
}
|
||||||
|
sharedPreferenceUtil.context.toast(
|
||||||
|
sharedPreferenceUtil.context.getString(
|
||||||
|
R.string.export_bookmark_saved,
|
||||||
|
bookmarkDestinationFile.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
Log.e(TAG, "Error: bookmark couldn't export.\n Original exception = $ignore")
|
||||||
|
sharedPreferenceUtil.context.toast(R.string.export_bookmark_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportedFile(fileName: String): File {
|
||||||
|
val rootFolder = File(
|
||||||
|
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}" +
|
||||||
|
"/org.kiwix"
|
||||||
|
)
|
||||||
|
if (!rootFolder.isFileExist()) rootFolder.mkdir()
|
||||||
|
return sequence {
|
||||||
|
yield(File(rootFolder, fileName))
|
||||||
|
yieldAll(
|
||||||
|
generateSequence(1) { it + 1 }.map {
|
||||||
|
File(
|
||||||
|
rootFolder, fileName.replace(".", "_$it.")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}.first { !it.isFileExist() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importBookmarks(bookmarkFile: File) {
|
||||||
|
// Create a temporary library manager to import the bookmarks.
|
||||||
|
val tempLibrary = Library()
|
||||||
|
Manager(tempLibrary).apply {
|
||||||
|
// Read the bookmark file.
|
||||||
|
readBookmarkFile(bookmarkFile.canonicalPath)
|
||||||
|
}
|
||||||
|
// Add the ZIM files to the library for validating the bookmarks.
|
||||||
|
bookDao.getBooks().forEach {
|
||||||
|
addBookToLibrary(file = it.file)
|
||||||
|
}
|
||||||
|
// Save the imported bookmarks to the current library.
|
||||||
|
tempLibrary.getBookmarks(false)?.toList()?.forEach {
|
||||||
|
saveBookmark(LibkiwixBookmarkItem(it, null, null))
|
||||||
|
}
|
||||||
|
sharedPreferenceUtil.context.toast(R.string.bookmark_imported_message)
|
||||||
|
|
||||||
|
if (bookmarkFile.exists()) {
|
||||||
|
bookmarkFile.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "LibkiwixBookmark"
|
const val TAG = "LibkiwixBookmark"
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import android.content.Context
|
|||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
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.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import org.kiwix.libkiwix.JNIKiwix
|
import org.kiwix.libkiwix.JNIKiwix
|
||||||
import org.kiwix.libkiwix.Library
|
import org.kiwix.libkiwix.Library
|
||||||
@ -45,6 +46,7 @@ class JNIModule {
|
|||||||
fun providesLibkiwixBookmarks(
|
fun providesLibkiwixBookmarks(
|
||||||
library: Library,
|
library: Library,
|
||||||
manager: Manager,
|
manager: Manager,
|
||||||
sharedPreferenceUtil: SharedPreferenceUtil
|
sharedPreferenceUtil: SharedPreferenceUtil,
|
||||||
): LibkiwixBookmarks = LibkiwixBookmarks(library, manager, sharedPreferenceUtil)
|
bookDao: NewBookDao
|
||||||
|
): LibkiwixBookmarks = LibkiwixBookmarks(library, manager, sharedPreferenceUtil, bookDao)
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,18 @@ package org.kiwix.kiwixmobile.core.settings
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity.RESULT_OK
|
import android.app.Activity.RESULT_OK
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
@ -43,8 +47,11 @@ import org.kiwix.kiwixmobile.core.NightModeConfig
|
|||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
|
||||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getVersionCode
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getVersionCode
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
import org.kiwix.kiwixmobile.core.main.AddNoteDialog
|
import org.kiwix.kiwixmobile.core.main.AddNoteDialog
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
|
import org.kiwix.kiwixmobile.core.navigateToAppSettings
|
||||||
import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION
|
import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION
|
||||||
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
||||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||||
@ -56,8 +63,10 @@ import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.OpenCredits
|
|||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.SelectFolder
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.SelectFolder
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getPathFromUri
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getPathFromUri
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
|
||||||
abstract class CorePrefsFragment :
|
abstract class CorePrefsFragment :
|
||||||
PreferenceFragmentCompat(),
|
PreferenceFragmentCompat(),
|
||||||
@ -83,6 +92,10 @@ abstract class CorePrefsFragment :
|
|||||||
@JvmField
|
@JvmField
|
||||||
@Inject
|
@Inject
|
||||||
protected var alertDialogShower: DialogShower? = null
|
protected var alertDialogShower: DialogShower? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
internal var libkiwixBookmarks: LibkiwixBookmarks? = null
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
coreComponent
|
coreComponent
|
||||||
.activityComponentBuilder()
|
.activityComponentBuilder()
|
||||||
@ -131,6 +144,8 @@ abstract class CorePrefsFragment :
|
|||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
presenter?.dispose()
|
presenter?.dispose()
|
||||||
|
storagePermissionForNotesLauncher?.unregister()
|
||||||
|
storagePermissionForNotesLauncher = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,9 +304,149 @@ abstract class CorePrefsFragment :
|
|||||||
if (preference.key.equals(SharedPreferenceUtil.PREF_STORAGE, ignoreCase = true)) {
|
if (preference.key.equals(SharedPreferenceUtil.PREF_STORAGE, ignoreCase = true)) {
|
||||||
openFolderSelect()
|
openFolderSelect()
|
||||||
}
|
}
|
||||||
|
if (preference.key.equals(PREF_EXPORT_BOOKMARK, ignoreCase = true) &&
|
||||||
|
requestExternalStorageWritePermissionForExportBookmark()
|
||||||
|
) {
|
||||||
|
showExportBookmarkDialog()
|
||||||
|
}
|
||||||
|
if (preference.key.equals(PREF_IMPORT_BOOKMARK, ignoreCase = true)) {
|
||||||
|
showImportBookmarkDialog()
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("NestedBlockDepth")
|
||||||
|
private fun requestExternalStorageWritePermissionForExportBookmark(): Boolean {
|
||||||
|
var isPermissionGranted = false
|
||||||
|
if (sharedPreferenceUtil?.isPlayStoreBuildWithAndroid11OrAbove() == false &&
|
||||||
|
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
|
||||||
|
) {
|
||||||
|
if (requireActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
isPermissionGranted = true
|
||||||
|
} else {
|
||||||
|
storagePermissionForNotesLauncher?.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isPermissionGranted = true
|
||||||
|
}
|
||||||
|
return isPermissionGranted
|
||||||
|
}
|
||||||
|
|
||||||
|
private var storagePermissionForNotesLauncher: ActivityResultLauncher<String>? =
|
||||||
|
registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestPermission()
|
||||||
|
) { isGranted ->
|
||||||
|
if (isGranted) {
|
||||||
|
// Successfully granted permission, so opening the export bookmark Dialog
|
||||||
|
showExportBookmarkDialog()
|
||||||
|
} else {
|
||||||
|
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||||
|
/* shouldShowRequestPermissionRationale() returns false when:
|
||||||
|
* 1) User has previously checked on "Don't ask me again", and/or
|
||||||
|
* 2) Permission has been disabled on device
|
||||||
|
*/
|
||||||
|
requireActivity().toast(
|
||||||
|
R.string.ext_storage_permission_rationale_export_bookmark,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
requireActivity().toast(
|
||||||
|
R.string.ext_storage_write_permission_denied_export_bookmark,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
|
alertDialogShower?.show(
|
||||||
|
KiwixDialog.ReadPermissionRequired,
|
||||||
|
requireActivity()::navigateToAppSettings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showExportBookmarkDialog() {
|
||||||
|
alertDialogShower?.show(
|
||||||
|
KiwixDialog.YesNoDialog.ExportBookmarks,
|
||||||
|
{ libkiwixBookmarks?.exportBookmark() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showImportBookmarkDialog() {
|
||||||
|
alertDialogShower?.show(
|
||||||
|
KiwixDialog.ImportBookmarks,
|
||||||
|
::showFileChooser
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showFileChooser() {
|
||||||
|
val intent = Intent().apply {
|
||||||
|
action = Intent.ACTION_GET_CONTENT
|
||||||
|
type = "*/*"
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a bookmark file"))
|
||||||
|
} catch (ex: ActivityNotFoundException) {
|
||||||
|
activity.toast(
|
||||||
|
resources.getString(R.string.no_app_found_to_select_bookmark_file),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val fileSelectLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
|
if (result.resultCode == RESULT_OK) {
|
||||||
|
result.data?.data?.let { uri ->
|
||||||
|
val contentResolver = requireActivity().contentResolver
|
||||||
|
if (!isValidBookmarkFile(contentResolver.getType(uri))) {
|
||||||
|
activity.toast(
|
||||||
|
resources.getString(R.string.error_invalid_bookmark_file),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
return@registerForActivityResult
|
||||||
|
}
|
||||||
|
|
||||||
|
createTempFile(contentResolver.openInputStream(uri)).apply {
|
||||||
|
if (isValidXmlFile(this)) {
|
||||||
|
libkiwixBookmarks?.importBookmarks(this)
|
||||||
|
} else {
|
||||||
|
activity.toast(
|
||||||
|
resources.getString(R.string.error_invalid_bookmark_file),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isValidXmlFile(file: File): Boolean {
|
||||||
|
return try {
|
||||||
|
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file)
|
||||||
|
true
|
||||||
|
} catch (ignore: Exception) {
|
||||||
|
Log.e("IMPORT_BOOKMARKS", "Invalid XML file", ignore)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTempFile(inputStream: InputStream?): File {
|
||||||
|
// create a temp file for importing the saved bookmarks
|
||||||
|
val tempFile = File(requireActivity().externalCacheDir, "bookmark.xml")
|
||||||
|
if (tempFile.exists()) {
|
||||||
|
tempFile.delete()
|
||||||
|
}
|
||||||
|
tempFile.createNewFile()
|
||||||
|
inputStream?.let {
|
||||||
|
tempFile.outputStream().use(inputStream::copyTo)
|
||||||
|
}
|
||||||
|
return tempFile
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isValidBookmarkFile(mimeType: String?) =
|
||||||
|
mimeType == "application/xml" || mimeType == "text/xml"
|
||||||
|
|
||||||
private fun openFolderSelect() {
|
private fun openFolderSelect() {
|
||||||
val dialogFragment = StorageSelectDialog()
|
val dialogFragment = StorageSelectDialog()
|
||||||
dialogFragment.onSelectAction =
|
dialogFragment.onSelectAction =
|
||||||
@ -383,5 +538,7 @@ abstract class CorePrefsFragment :
|
|||||||
private const val ZOOM_OFFSET = 2
|
private const val ZOOM_OFFSET = 2
|
||||||
private const val ZOOM_SCALE = 25
|
private const val ZOOM_SCALE = 25
|
||||||
private const val INTERNAL_TEXT_ZOOM = "text_zoom"
|
private const val INTERNAL_TEXT_ZOOM = "text_zoom"
|
||||||
|
private const val PREF_EXPORT_BOOKMARK = "pref_export_bookmark"
|
||||||
|
private const val PREF_IMPORT_BOOKMARK = "pref_import_bookmark"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,6 +272,11 @@ sealed class KiwixDialog(
|
|||||||
object OpenInNewTab : YesNoDialog(
|
object OpenInNewTab : YesNoDialog(
|
||||||
null, R.string.open_in_new_tab
|
null, R.string.open_in_new_tab
|
||||||
)
|
)
|
||||||
|
|
||||||
|
object ExportBookmarks : YesNoDialog(
|
||||||
|
R.string.export_all_bookmarks_dialog_title,
|
||||||
|
message = R.string.export_all_bookmarks_dialog_message,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
object StorageConfigure : KiwixDialog(
|
object StorageConfigure : KiwixDialog(
|
||||||
@ -282,6 +287,13 @@ sealed class KiwixDialog(
|
|||||||
icon = R.drawable.ic_baseline_storage_24
|
icon = R.drawable.ic_baseline_storage_24
|
||||||
)
|
)
|
||||||
|
|
||||||
|
object ImportBookmarks : KiwixDialog(
|
||||||
|
R.string.import_bookmarks_dialog_title,
|
||||||
|
message = null,
|
||||||
|
positiveMessage = R.string.yes,
|
||||||
|
negativeMessage = R.string.no
|
||||||
|
)
|
||||||
|
|
||||||
object DeleteSelectedHistory : KiwixDialog(
|
object DeleteSelectedHistory : KiwixDialog(
|
||||||
R.string.delete_selected_history,
|
R.string.delete_selected_history,
|
||||||
null,
|
null,
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
<string name="tts_lang_not_supported">The language of this page is not supported. The article may not be properly read.</string>
|
<string name="tts_lang_not_supported">The language of this page is not supported. The article may not be properly read.</string>
|
||||||
<string name="no_reader_application_installed">Could not find an installed application for this type of file</string>
|
<string name="no_reader_application_installed">Could not find an installed application for this type of file</string>
|
||||||
<string name="no_email_application_installed">Please install an email service provider or email us at %1s</string>
|
<string name="no_email_application_installed">Please install an email service provider or email us at %1s</string>
|
||||||
|
<string name="no_app_found_to_select_bookmark_file">No app found to select a bookmark file</string>
|
||||||
<string name="no_section_info">No Content Headers Found</string>
|
<string name="no_section_info">No Content Headers Found</string>
|
||||||
<string name="request_storage">To access offline content we need access to your storage</string>
|
<string name="request_storage">To access offline content we need access to your storage</string>
|
||||||
<string name="request_write_storage">To download zim files we need write access to your storage</string>
|
<string name="request_write_storage">To download zim files we need write access to your storage</string>
|
||||||
@ -77,6 +78,11 @@
|
|||||||
<string name="pref_clear_all_history_summary">Clear recent searches and tabs history</string>
|
<string name="pref_clear_all_history_summary">Clear recent searches and tabs history</string>
|
||||||
<string name="pref_notes">Notes</string>
|
<string name="pref_notes">Notes</string>
|
||||||
<string name="pref_permission">Permissions</string>
|
<string name="pref_permission">Permissions</string>
|
||||||
|
<string name="pref_import_bookmark_title">Import Bookmarks</string>
|
||||||
|
<string name="pref_import_bookmark_summary">Import the saved bookmarks</string>
|
||||||
|
<string name="pref_export_bookmark_title">Export Bookmarks</string>
|
||||||
|
<string name="pref_export_bookmark_summary">Export all saved bookmarks</string>
|
||||||
|
<string name="export_bookmark_saved">Bookmarks are exported in %s file</string>
|
||||||
<string name="all_history_cleared">All History Cleared</string>
|
<string name="all_history_cleared">All History Cleared</string>
|
||||||
<string name="pref_clear_all_bookmarks_title">Clear bookmarks</string>
|
<string name="pref_clear_all_bookmarks_title">Clear bookmarks</string>
|
||||||
<string name="clear_all_history_dialog_title">Clear All History?</string>
|
<string name="clear_all_history_dialog_title">Clear All History?</string>
|
||||||
@ -226,6 +232,9 @@
|
|||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="note">Note</string>
|
<string name="note">Note</string>
|
||||||
<string name="wiki_article_title">Wiki Article Title</string>
|
<string name="wiki_article_title">Wiki Article Title</string>
|
||||||
|
<string name="ext_storage_permission_rationale_export_bookmark">Storage access is required for exporting Bookmarks</string>
|
||||||
|
<string name="ext_storage_write_permission_denied_export_bookmark">Bookmarks can’t export without access of storage</string>
|
||||||
|
<string name="export_bookmark_error">An error occurred when trying to export bookmark!</string>
|
||||||
<string name="ext_storage_permission_rationale_add_note">Storage access is required for Notes</string>
|
<string name="ext_storage_permission_rationale_add_note">Storage access is required for Notes</string>
|
||||||
<string name="ext_storage_write_permission_denied_add_note">Notes can\’t be used without access to storage</string>
|
<string name="ext_storage_write_permission_denied_add_note">Notes can\’t be used without access to storage</string>
|
||||||
<string name="note_save_unsuccessful">Note save unsuccessful</string>
|
<string name="note_save_unsuccessful">Note save unsuccessful</string>
|
||||||
@ -288,6 +297,11 @@
|
|||||||
<string name="delete_selected_history">Delete Selected History?</string>
|
<string name="delete_selected_history">Delete Selected History?</string>
|
||||||
<string name="delete_bookmarks">Delete All Bookmarks?</string>
|
<string name="delete_bookmarks">Delete All Bookmarks?</string>
|
||||||
<string name="delete_selected_bookmarks">Delete Selected Bookmarks?</string>
|
<string name="delete_selected_bookmarks">Delete Selected Bookmarks?</string>
|
||||||
|
<string name="import_bookmarks_dialog_title">Import Bookmarks?</string>
|
||||||
|
<string name="export_all_bookmarks_dialog_title">Export All Bookmarks?</string>
|
||||||
|
<string name="export_all_bookmarks_dialog_message">Exporting will generate bookmark.xml file in the Download/org.kiwix…/ folder.</string>
|
||||||
|
<string name="bookmark_imported_message">All the bookmarks has been imported.</string>
|
||||||
|
<string name="error_invalid_bookmark_file">Error: The selected file is not a valid bookmark file.</string>
|
||||||
<string name="on">On</string>
|
<string name="on">On</string>
|
||||||
<string name="off">Off</string>
|
<string name="off">Off</string>
|
||||||
<string name="auto">Auto</string>
|
<string name="auto">Auto</string>
|
||||||
|
@ -95,6 +95,25 @@
|
|||||||
android:title="@string/pref_clear_all_notes_title"
|
android:title="@string/pref_clear_all_notes_title"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_notes"
|
||||||
|
android:title="@string/bookmarks"
|
||||||
|
app:iconSpaceReserved="false">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="pref_import_bookmark"
|
||||||
|
android:summary="@string/pref_import_bookmark_summary"
|
||||||
|
android:title="@string/pref_import_bookmark_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="pref_export_bookmark"
|
||||||
|
android:summary="@string/pref_export_bookmark_summary"
|
||||||
|
android:title="@string/pref_export_bookmark_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="pref_permissions"
|
android:key="pref_permissions"
|
||||||
|
@ -29,6 +29,7 @@ import org.junit.jupiter.api.AfterAll
|
|||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
|
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
|
||||||
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Factory
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Factory
|
||||||
@ -50,6 +51,7 @@ class StorageObserverTest {
|
|||||||
private val file: File = mockk()
|
private val file: File = mockk()
|
||||||
private val readerFactory: Factory = mockk()
|
private val readerFactory: Factory = mockk()
|
||||||
private val zimFileReader: ZimFileReader = mockk()
|
private val zimFileReader: ZimFileReader = mockk()
|
||||||
|
private val libkiwixBookmarks: LibkiwixBookmarks = mockk()
|
||||||
private val scanningProgressListener: ScanningProgressListener = mockk()
|
private val scanningProgressListener: ScanningProgressListener = mockk()
|
||||||
|
|
||||||
private val files: PublishProcessor<List<File>> = PublishProcessor.create()
|
private val files: PublishProcessor<List<File>> = PublishProcessor.create()
|
||||||
@ -71,8 +73,9 @@ class StorageObserverTest {
|
|||||||
every { sharedPreferenceUtil.prefStorage } returns "a"
|
every { sharedPreferenceUtil.prefStorage } returns "a"
|
||||||
every { fileSearch.scan(scanningProgressListener) } returns files
|
every { fileSearch.scan(scanningProgressListener) } returns files
|
||||||
every { downloadDao.downloads() } returns downloads
|
every { downloadDao.downloads() } returns downloads
|
||||||
|
every { zimFileReader.jniKiwixReader } returns mockk()
|
||||||
every { runBlocking { readerFactory.create(file) } } returns zimFileReader
|
every { runBlocking { readerFactory.create(file) } } returns zimFileReader
|
||||||
storageObserver = StorageObserver(downloadDao, fileSearch, readerFactory)
|
storageObserver = StorageObserver(downloadDao, fileSearch, readerFactory, libkiwixBookmarks)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user