mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-20 18:48:16 -04:00
Refactored the whole code to use ZimReaderSource
This commit is contained in:
parent
da51cfc02d
commit
811e37bf70
@ -43,6 +43,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
||||
import org.kiwix.kiwixmobile.core.data.remote.ObjectBoxToLibkiwixMigrator
|
||||
import org.kiwix.kiwixmobile.core.di.modules.DatabaseModule
|
||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
@ -74,6 +75,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedZimId,
|
||||
expectedZimName,
|
||||
expectedZimFilePath,
|
||||
ZimReaderSource(File(expectedZimFilePath)),
|
||||
expectedBookmarkUrl,
|
||||
expectedTitle,
|
||||
expectedFavicon
|
||||
@ -156,7 +158,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
assertEquals(actualDataAfterMigration[0].zimFilePath, expectedZimFilePath)
|
||||
assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), expectedZimFilePath)
|
||||
assertEquals(actualDataAfterMigration[0].zimId, expectedZimId)
|
||||
assertEquals(actualDataAfterMigration[0].title, expectedTitle)
|
||||
assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl)
|
||||
@ -185,6 +187,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedZimId,
|
||||
expectedZimName,
|
||||
expectedZimFilePath,
|
||||
ZimReaderSource(File(expectedZimFilePath)),
|
||||
existingBookmarkUrl,
|
||||
existingTitle,
|
||||
expectedFavicon
|
||||
@ -226,6 +229,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedZimId,
|
||||
expectedZimName,
|
||||
expectedZimFilePath,
|
||||
ZimReaderSource(File(expectedZimFilePath)),
|
||||
"https://alpine_linux/search_$i",
|
||||
"title_$i",
|
||||
expectedFavicon
|
||||
@ -250,6 +254,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedZimId,
|
||||
expectedZimName,
|
||||
null,
|
||||
null,
|
||||
expectedBookmarkUrl,
|
||||
expectedTitle,
|
||||
expectedFavicon
|
||||
@ -261,7 +266,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
assertEquals(actualDataAfterMigration[0].zimFilePath, null)
|
||||
assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), null)
|
||||
assertEquals(actualDataAfterMigration[0].zimId, expectedZimId)
|
||||
assertEquals(actualDataAfterMigration[0].title, expectedTitle)
|
||||
assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl)
|
||||
@ -278,6 +283,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedZimId,
|
||||
expectedZimName,
|
||||
nonExistingPath,
|
||||
ZimReaderSource(File(nonExistingPath)),
|
||||
expectedBookmarkUrl,
|
||||
expectedTitle,
|
||||
expectedFavicon
|
||||
@ -289,7 +295,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().blockingFirst()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
assertEquals(actualDataAfterMigration[0].zimFilePath, null)
|
||||
assertEquals(actualDataAfterMigration[0].zimReaderSource?.toDatabase(), null)
|
||||
assertEquals(actualDataAfterMigration[0].zimId, expectedZimId)
|
||||
assertEquals(actualDataAfterMigration[0].title, expectedTitle)
|
||||
assertEquals(actualDataAfterMigration[0].url, expectedBookmarkUrl)
|
||||
|
@ -31,11 +31,11 @@ import org.junit.Test
|
||||
import org.kiwix.kiwixmobile.BaseActivityTest
|
||||
import org.kiwix.kiwixmobile.core.DarkModeConfig
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
|
||||
import org.kiwix.libzim.Archive
|
||||
import org.kiwix.libzim.SuggestionSearcher
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@ -81,12 +81,11 @@ class MimeTypeTest : BaseActivityTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
val archive = Archive(zimFile.canonicalPath)
|
||||
val zimSource = ZimReaderSource(zimFile)
|
||||
val archive = zimSource.createArchive()
|
||||
val zimFileReader = ZimFileReader(
|
||||
zimFile,
|
||||
emptyList(),
|
||||
null,
|
||||
archive,
|
||||
zimSource,
|
||||
archive!!,
|
||||
DarkModeConfig(SharedPreferenceUtil(context), context),
|
||||
SuggestionSearcher(archive)
|
||||
)
|
||||
|
@ -31,11 +31,11 @@ import org.junit.Test
|
||||
import org.kiwix.kiwixmobile.BaseActivityTest
|
||||
import org.kiwix.kiwixmobile.core.DarkModeConfig
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils
|
||||
import org.kiwix.libzim.Archive
|
||||
import org.kiwix.libzim.SuggestionSearcher
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
@ -89,12 +89,11 @@ class EncodedUrlTest : BaseActivityTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
val archive = Archive(zimFile.canonicalPath)
|
||||
val zimReaderSource = ZimReaderSource(zimFile)
|
||||
val archive = zimReaderSource.createArchive()
|
||||
val zimFileReader = ZimFileReader(
|
||||
zimFile,
|
||||
emptyList(),
|
||||
null,
|
||||
archive,
|
||||
zimReaderSource,
|
||||
archive!!,
|
||||
DarkModeConfig(SharedPreferenceUtil(context), context),
|
||||
SuggestionSearcher(archive)
|
||||
)
|
||||
|
@ -220,7 +220,7 @@ class KiwixMainActivity : CoreMainActivity() {
|
||||
{
|
||||
intent.getStringExtra(DOWNLOAD_NOTIFICATION_TITLE)?.let {
|
||||
newBookDao.bookMatching(it)?.let { bookOnDiskEntity ->
|
||||
openZimFromFilePath(bookOnDiskEntity.file.path)
|
||||
openZimFromFilePath(bookOnDiskEntity.zimReaderSource.toDatabase())
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -75,6 +75,7 @@ import org.kiwix.kiwixmobile.core.main.MainRepositoryActions
|
||||
import org.kiwix.kiwixmobile.core.navigateToAppSettings
|
||||
import org.kiwix.kiwixmobile.core.navigateToSettings
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener
|
||||
@ -405,9 +406,9 @@ class LocalLibraryFragment : BaseFragment() {
|
||||
// we can directly add it to the database.
|
||||
// See https://github.com/kiwix/kiwix-android/issues/3650
|
||||
runBlocking {
|
||||
zimReaderFactory.create(file)
|
||||
zimReaderFactory.create(ZimReaderSource(file))
|
||||
?.let { zimFileReader ->
|
||||
BookOnDisk(file, zimFileReader).also {
|
||||
BookOnDisk(zimFileReader).also {
|
||||
mainRepositoryActions.saveBook(it)
|
||||
zimFileReader.dispose()
|
||||
}
|
||||
|
@ -54,11 +54,14 @@ import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||
import org.kiwix.kiwixmobile.core.main.CoreReaderFragment
|
||||
import org.kiwix.kiwixmobile.core.main.CoreWebViewClient
|
||||
import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE
|
||||
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
|
||||
import org.kiwix.kiwixmobile.core.utils.files.Log
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import java.io.File
|
||||
|
||||
private const val HIDE_TAB_SWITCHER_DELAY: Long = 300
|
||||
@ -124,7 +127,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
||||
activity.toast(string.error_file_not_found)
|
||||
return
|
||||
}
|
||||
openZimFile(File(filePath))
|
||||
openZimFile(ZimReaderSource(File(filePath)))
|
||||
}
|
||||
|
||||
override fun loadDrawerViews() {
|
||||
@ -200,9 +203,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (zimReaderContainer?.zimFile == null &&
|
||||
zimReaderContainer?.zimFileReader?.assetFileDescriptorList?.isEmpty() == true
|
||||
) {
|
||||
if (zimReaderContainer?.zimReaderSource == null) {
|
||||
exitBook()
|
||||
}
|
||||
if (isFullScreenVideo || isInFullScreenMode()) {
|
||||
@ -221,14 +222,14 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
||||
currentTab: Int
|
||||
) {
|
||||
val settings = requireActivity().getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0)
|
||||
val zimFile = settings.getString(TAG_CURRENT_FILE, null)
|
||||
val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null))
|
||||
|
||||
if (zimFile != null && File(zimFile).isFileExist()) {
|
||||
if (zimReaderContainer?.zimFile == null) {
|
||||
openZimFile(File(zimFile))
|
||||
if (zimReaderSource != null && zimReaderSource.canOpenInLibkiwix()) {
|
||||
if (zimReaderContainer?.zimReaderSource == null) {
|
||||
openZimFile(zimReaderSource)
|
||||
Log.d(
|
||||
TAG_KIWIX,
|
||||
"Kiwix normal start, Opened last used zimFile: -> $zimFile"
|
||||
"Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}"
|
||||
)
|
||||
} else {
|
||||
zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
|
||||
@ -305,21 +306,13 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
||||
when (it.scheme) {
|
||||
"file" -> {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
openZimFile(it.toFile()).also {
|
||||
// if used once then clear it to avoid affecting any other functionality
|
||||
// of the application.
|
||||
requireActivity().intent.action = null
|
||||
}
|
||||
openAndSaveZimFileInLocalLibrary(it.toFile())
|
||||
}, 300)
|
||||
}
|
||||
|
||||
"content" -> {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
getZimFileFromUri(it)?.let { zimFile ->
|
||||
openZimFile(zimFile)
|
||||
}.also {
|
||||
requireActivity().intent.action = null
|
||||
}
|
||||
getZimFileFromUri(it)?.let(::openAndSaveZimFileInLocalLibrary)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
@ -329,6 +322,29 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
||||
return ShouldCall
|
||||
}
|
||||
|
||||
private fun openAndSaveZimFileInLocalLibrary(file: File) {
|
||||
val zimReaderSource = ZimReaderSource(file)
|
||||
if (zimReaderSource.canOpenInLibkiwix()) {
|
||||
zimReaderContainer?.let { zimReaderContainer ->
|
||||
zimReaderContainer.setZimReaderSource(zimReaderSource)
|
||||
|
||||
zimReaderContainer.zimFileReader?.let { zimFileReader ->
|
||||
BooksOnDiskListItem.BookOnDisk(zimFileReader).also { bookOnDisk ->
|
||||
// save the book in the library
|
||||
repositoryActions?.saveBook(bookOnDisk)
|
||||
zimFileReader.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
openZimFile(ZimReaderSource(file))
|
||||
} else {
|
||||
activity.toast(R.string.cannot_open_file)
|
||||
}
|
||||
// if used once then clear it to avoid affecting any other functionality
|
||||
// of the application.
|
||||
requireActivity().intent.action = null
|
||||
}
|
||||
|
||||
private fun getZimFileFromUri(
|
||||
uri: Uri
|
||||
): File? {
|
||||
|
@ -59,17 +59,20 @@ data class DeleteFiles(private val booksOnDiskListItems: List<BookOnDisk>) :
|
||||
private fun List<BookOnDisk>.deleteAll(): Boolean {
|
||||
return fold(true) { acc, book ->
|
||||
acc && deleteSpecificZimFile(book).also {
|
||||
if (it && book.file.canonicalPath == zimReaderContainer.zimCanonicalPath) {
|
||||
zimReaderContainer.setZimFile(null)
|
||||
if (it && book.zimReaderSource == zimReaderContainer.zimReaderSource) {
|
||||
zimReaderContainer.setZimReaderSource(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteSpecificZimFile(book: BookOnDisk): Boolean {
|
||||
val file = book.file
|
||||
FileUtils.deleteZimFile(file.path)
|
||||
if (file.isFileExist()) {
|
||||
val file = book.zimReaderSource.file
|
||||
file?.let {
|
||||
@Suppress("UnreachableCode")
|
||||
FileUtils.deleteZimFile(it.path)
|
||||
}
|
||||
if (file?.isFileExist() == true) {
|
||||
return false
|
||||
}
|
||||
newBookDao.delete(book.databaseId)
|
||||
|
@ -19,11 +19,9 @@
|
||||
package org.kiwix.kiwixmobile.zimManager.fileselectView.effects
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.net.toUri
|
||||
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.canReadFile
|
||||
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader
|
||||
@ -32,12 +30,14 @@ data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.Bo
|
||||
SideEffect<Unit> {
|
||||
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
val file = bookOnDisk.file
|
||||
if (!file.canReadFile()) {
|
||||
val zimReaderSource = bookOnDisk.zimReaderSource
|
||||
if (!zimReaderSource.canOpenInLibkiwix()) {
|
||||
activity.toast(R.string.error_file_not_found)
|
||||
} else {
|
||||
activity.navigate(
|
||||
actionNavigationLibraryToNavigationReader().apply { zimFileUri = file.toUri().toString() }
|
||||
actionNavigationLibraryToNavigationReader().apply {
|
||||
zimFileUri = zimReaderSource.toDatabase()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
package org.kiwix.kiwixmobile.zimManager.fileselectView.effects
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.os.bundleOf
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
@ -31,11 +30,7 @@ data class ShareFiles(private val selectedBooks: List<BookOnDisk>) :
|
||||
SideEffect<Unit> {
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
val selectedFileContentURIs = selectedBooks.mapNotNull {
|
||||
FileProvider.getUriForFile(
|
||||
activity,
|
||||
activity.packageName + ".fileprovider",
|
||||
it.file
|
||||
)
|
||||
it.zimReaderSource.getUri(activity)
|
||||
}
|
||||
activity.navigate(
|
||||
R.id.localFileTransferFragment,
|
||||
|
@ -26,6 +26,7 @@ import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.files.FileSearch
|
||||
import org.kiwix.kiwixmobile.core.utils.files.ScanningProgressListener
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
@ -57,9 +58,9 @@ class StorageObserver @Inject constructor(
|
||||
downloads.firstOrNull { file.absolutePath.endsWith(it.fileNameFromUrl) } == null
|
||||
|
||||
private fun convertToBookOnDisk(file: File) = runBlocking {
|
||||
zimReaderFactory.create(file)
|
||||
zimReaderFactory.create(ZimReaderSource(file))
|
||||
?.let { zimFileReader ->
|
||||
BookOnDisk(file, zimFileReader).also {
|
||||
BookOnDisk(zimFileReader).also {
|
||||
// add the book to libkiwix library to validate the imported bookmarks
|
||||
libkiwixBookmarks.addBookToLibrary(archive = zimFileReader.jniKiwixReader)
|
||||
zimFileReader.dispose()
|
||||
|
@ -36,7 +36,6 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
|
||||
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.bookmark.adapter.BookmarkItem
|
||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||
import org.kiwix.kiwixmobile.core.reader.ILLUSTRATION_SIZE
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
|
@ -149,7 +149,7 @@ open class ErrorActivity : BaseActivity() {
|
||||
}
|
||||
return """
|
||||
Current Zim File:
|
||||
${zimReaderContainer.zimCanonicalPath}
|
||||
${zimReaderContainer.zimReaderSource?.toDatabase()}
|
||||
All Zim Files in DB:
|
||||
$allZimFiles
|
||||
|
||||
|
@ -119,7 +119,7 @@ class AddNoteDialog : DialogFragment() {
|
||||
.inject(this)
|
||||
|
||||
// Returns name of the form ".../Kiwix/granbluefantasy_en_all_all_nopic_2018-10.zim"
|
||||
zimFileName = zimReaderContainer.zimCanonicalPath ?: zimReaderContainer.name
|
||||
zimFileName = zimReaderContainer.zimReaderSource?.toDatabase() ?: zimReaderContainer.name
|
||||
if (zimFileName != null) { // No zim file currently opened
|
||||
zimFileTitle = zimReaderContainer.zimFileTitle
|
||||
zimId = zimReaderContainer.id.orEmpty()
|
||||
|
@ -57,6 +57,7 @@ import org.kiwix.kiwixmobile.core.extensions.getToolbarNavigationIcon
|
||||
import org.kiwix.kiwixmobile.core.extensions.registerReceiver
|
||||
import org.kiwix.kiwixmobile.core.extensions.setToolTipWithContentDescription
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.search.NAV_ARG_SEARCH_STRING
|
||||
import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE
|
||||
import org.kiwix.kiwixmobile.core.utils.ExternalLinkOpener
|
||||
@ -372,12 +373,20 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
)
|
||||
}
|
||||
|
||||
fun openPage(pageUrl: String, zimFilePath: String = "", shouldOpenInNewTab: Boolean = false) {
|
||||
fun openPage(
|
||||
pageUrl: String,
|
||||
zimReaderSource: ZimReaderSource? = null,
|
||||
shouldOpenInNewTab: Boolean = false
|
||||
) {
|
||||
var zimFileUri = ""
|
||||
if (zimReaderSource != null) {
|
||||
zimFileUri = zimReaderSource.toDatabase()
|
||||
}
|
||||
navigate(
|
||||
readerFragmentResId,
|
||||
bundleOf(
|
||||
PAGE_URL_KEY to pageUrl,
|
||||
ZIM_FILE_URI_KEY to zimFilePath,
|
||||
ZIM_FILE_URI_KEY to zimFileUri,
|
||||
SHOULD_OPEN_IN_NEW_TAB to shouldOpenInNewTab
|
||||
)
|
||||
)
|
||||
|
@ -26,7 +26,6 @@ import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.AssetFileDescriptor
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Canvas
|
||||
import android.media.AudioManager
|
||||
@ -107,7 +106,6 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.requestNotificat
|
||||
import org.kiwix.kiwixmobile.core.extensions.ViewGroupExtensions.findFirstTextView
|
||||
import org.kiwix.kiwixmobile.core.extensions.closeFullScreenMode
|
||||
import org.kiwix.kiwixmobile.core.extensions.getToolbarNavigationIcon
|
||||
import org.kiwix.kiwixmobile.core.extensions.isFileExist
|
||||
import org.kiwix.kiwixmobile.core.extensions.setToolTipWithContentDescription
|
||||
import org.kiwix.kiwixmobile.core.extensions.showFullScreenMode
|
||||
import org.kiwix.kiwixmobile.core.extensions.snack
|
||||
@ -131,6 +129,7 @@ import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_S
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader.Companion.CONTENT_PREFIX
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen
|
||||
import org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate
|
||||
import org.kiwix.kiwixmobile.core.utils.DimenUtils.getToolbarHeight
|
||||
@ -159,7 +158,6 @@ import org.kiwix.kiwixmobile.core.utils.files.Log
|
||||
import org.kiwix.kiwixmobile.core.utils.titleToUrl
|
||||
import org.kiwix.kiwixmobile.core.utils.urlSuffixToParsableUrl
|
||||
import org.kiwix.libkiwix.Book
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@ -286,11 +284,11 @@ abstract class CoreReaderFragment :
|
||||
private var tts: KiwixTextToSpeech? = null
|
||||
private var compatCallback: CompatFindActionModeCallback? = null
|
||||
private var tabsAdapter: TabsAdapter? = null
|
||||
private var file: File? = null
|
||||
private var zimReaderSource: ZimReaderSource? = null
|
||||
private var actionMode: ActionMode? = null
|
||||
private var tempWebViewForUndo: KiwixWebView? = null
|
||||
private var tempWebViewListForUndo: MutableList<KiwixWebView> = ArrayList()
|
||||
private var tempZimFileForUndo: File? = null
|
||||
private var tempZimSourceForUndo: ZimReaderSource? = null
|
||||
private var isFirstRun = false
|
||||
private var tableDrawerAdapter: TableDrawerAdapter? = null
|
||||
private var tableDrawerRight: RecyclerView? = null
|
||||
@ -1323,7 +1321,7 @@ abstract class CoreReaderFragment :
|
||||
// Address those issues when the user frequently clicks on the close icon of the same tab.
|
||||
// See https://github.com/kiwix/kiwix-android/issues/3790 for more details.
|
||||
if (index == RecyclerView.NO_POSITION) return
|
||||
tempZimFileForUndo = zimReaderContainer?.zimFile
|
||||
tempZimSourceForUndo = zimReaderContainer?.zimReaderSource
|
||||
tempWebViewForUndo = webViewList[index]
|
||||
webViewList.removeAt(index)
|
||||
if (index <= currentWebViewIndex && currentWebViewIndex > 0) {
|
||||
@ -1360,7 +1358,7 @@ abstract class CoreReaderFragment :
|
||||
}
|
||||
|
||||
private fun closeZimBook() {
|
||||
zimReaderContainer?.setZimFile(null)
|
||||
zimReaderContainer?.setZimReaderSource(null)
|
||||
}
|
||||
|
||||
private fun restoreDeletedTab(index: Int) {
|
||||
@ -1378,7 +1376,7 @@ abstract class CoreReaderFragment :
|
||||
LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
zimReaderContainer?.setZimFile(tempZimFileForUndo)
|
||||
zimReaderContainer?.setZimReaderSource(tempZimSourceForUndo)
|
||||
webViewList.add(index, it)
|
||||
tabsAdapter?.notifyDataSetChanged()
|
||||
snackBarRoot?.let { root ->
|
||||
@ -1617,33 +1615,21 @@ abstract class CoreReaderFragment :
|
||||
unsupportedMimeTypeHandler?.showSaveOrOpenUnsupportedFilesDialog(url, documentType)
|
||||
}
|
||||
|
||||
fun openZimFile(
|
||||
file: File?,
|
||||
isCustomApp: Boolean = false,
|
||||
assetFileDescriptorList: List<AssetFileDescriptor> = emptyList(),
|
||||
filePath: String? = null
|
||||
) {
|
||||
fun openZimFile(zimReaderSource: ZimReaderSource, isCustomApp: Boolean = false) {
|
||||
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) || isCustomApp) {
|
||||
if (file?.isFileExist() == true) {
|
||||
if (zimReaderSource.canOpenInLibkiwix()) {
|
||||
// Show content if there is `Open Library` button showing
|
||||
// and we are opening the ZIM file
|
||||
reopenBook()
|
||||
openAndSetInContainer(file = file)
|
||||
updateTitle()
|
||||
} else if (assetFileDescriptorList.isNotEmpty()) {
|
||||
reopenBook()
|
||||
openAndSetInContainer(
|
||||
assetFileDescriptorList = assetFileDescriptorList,
|
||||
filePath = filePath
|
||||
)
|
||||
openAndSetInContainer(zimReaderSource)
|
||||
updateTitle()
|
||||
} else {
|
||||
exitBook()
|
||||
Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + file?.absolutePath)
|
||||
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.file = file
|
||||
this.zimReaderSource = zimReaderSource
|
||||
requestExternalStoragePermission()
|
||||
}
|
||||
}
|
||||
@ -1666,27 +1652,16 @@ abstract class CoreReaderFragment :
|
||||
)
|
||||
}
|
||||
|
||||
private fun openAndSetInContainer(
|
||||
file: File? = null,
|
||||
assetFileDescriptorList: List<AssetFileDescriptor> = emptyList(),
|
||||
filePath: String? = null
|
||||
) {
|
||||
private fun openAndSetInContainer(zimReaderSource: ZimReaderSource) {
|
||||
try {
|
||||
if (isNotPreviouslyOpenZim(file?.canonicalPath)) {
|
||||
if (isNotPreviouslyOpenZim(zimReaderSource)) {
|
||||
webViewList.clear()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
zimReaderContainer?.let { zimReaderContainer ->
|
||||
if (assetFileDescriptorList.isNotEmpty()) {
|
||||
zimReaderContainer.setZimFileDescriptor(
|
||||
assetFileDescriptorList,
|
||||
filePath = filePath
|
||||
)
|
||||
} else {
|
||||
zimReaderContainer.setZimFile(file)
|
||||
}
|
||||
zimReaderContainer.setZimReaderSource(zimReaderSource)
|
||||
|
||||
val zimFileReader = zimReaderContainer.zimFileReader
|
||||
zimFileReader?.let { zimFileReader ->
|
||||
@ -1721,8 +1696,8 @@ abstract class CoreReaderFragment :
|
||||
bookmarkingDisposable?.dispose()
|
||||
}
|
||||
|
||||
private fun isNotPreviouslyOpenZim(canonicalPath: String?): Boolean =
|
||||
canonicalPath != null && canonicalPath != zimReaderContainer?.zimCanonicalPath
|
||||
private fun isNotPreviouslyOpenZim(zimReaderSource: ZimReaderSource?): Boolean =
|
||||
zimReaderSource != null && zimReaderSource != zimReaderContainer?.zimReaderSource
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
@ -1732,7 +1707,7 @@ abstract class CoreReaderFragment :
|
||||
when (requestCode) {
|
||||
REQUEST_STORAGE_PERMISSION -> {
|
||||
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||
file?.let(::openZimFile)
|
||||
zimReaderSource?.let(::openZimFile)
|
||||
} else {
|
||||
snackBarRoot?.let { snackBarRoot ->
|
||||
Snackbar.make(snackBarRoot, R.string.request_storage, Snackbar.LENGTH_LONG)
|
||||
@ -1761,7 +1736,7 @@ abstract class CoreReaderFragment :
|
||||
rotate()
|
||||
setIsCloseAllTabButtonClickable(false)
|
||||
}
|
||||
tempZimFileForUndo = zimReaderContainer?.zimFile
|
||||
tempZimSourceForUndo = zimReaderContainer?.zimReaderSource
|
||||
tempWebViewListForUndo.apply {
|
||||
clear()
|
||||
addAll(webViewList)
|
||||
@ -1788,7 +1763,7 @@ abstract class CoreReaderFragment :
|
||||
|
||||
private fun restoreDeletedTabs() {
|
||||
if (tempWebViewListForUndo.isNotEmpty()) {
|
||||
zimReaderContainer?.setZimFile(tempZimFileForUndo)
|
||||
zimReaderContainer?.setZimReaderSource(tempZimSourceForUndo)
|
||||
webViewList.addAll(tempWebViewListForUndo)
|
||||
tabsAdapter?.notifyDataSetChanged()
|
||||
snackBarRoot?.let { root ->
|
||||
@ -2131,7 +2106,7 @@ abstract class CoreReaderFragment :
|
||||
urls.put(view.url)
|
||||
positions.put(view.scrollY)
|
||||
}
|
||||
editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimCanonicalPath)
|
||||
editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase())
|
||||
editor.putString(TAG_CURRENT_ARTICLES, "$urls")
|
||||
editor.putString(TAG_CURRENT_POSITIONS, "$positions")
|
||||
editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex)
|
||||
@ -2143,7 +2118,8 @@ abstract class CoreReaderFragment :
|
||||
saveTabStates()
|
||||
Log.d(
|
||||
TAG_KIWIX,
|
||||
"onPause Save current zim file to preferences: " + zimReaderContainer?.zimCanonicalPath
|
||||
"onPause Save current zim file to preferences: " +
|
||||
"${zimReaderContainer?.zimReaderSource?.toDatabase()}"
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ sealed class HistoryListItem : PageRelated {
|
||||
val databaseId: Long = 0L,
|
||||
override val zimId: String,
|
||||
val zimName: String,
|
||||
override val zimReaderSource: ZimReaderSource,
|
||||
override val zimReaderSource: ZimReaderSource?,
|
||||
override val favicon: String?,
|
||||
val historyUrl: String,
|
||||
override val title: String,
|
||||
|
@ -23,6 +23,7 @@ import io.reactivex.processors.PublishProcessor
|
||||
import org.json.JSONArray
|
||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isCustomApp
|
||||
import org.kiwix.kiwixmobile.core.page.adapter.Page
|
||||
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
|
||||
import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenNote
|
||||
@ -36,7 +37,6 @@ import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_POSITIONS
|
||||
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_TAB
|
||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.ShowNoteDialog
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
data class ShowOpenNoteDialog(
|
||||
@ -52,14 +52,15 @@ data class ShowOpenNoteDialog(
|
||||
{ effects.offer(OpenPage(page, zimReaderContainer)) },
|
||||
{
|
||||
val item = page as NoteListItem
|
||||
// Check if zimFilePath is not null, and then set it in zimReaderContainer.
|
||||
// Check if toDatabase is not null, and then set it in zimReaderContainer.
|
||||
// For custom apps, we are currently using fileDescriptor, and they only have a single file in them,
|
||||
// which is already set in zimReaderContainer, so there's no need to set it again.
|
||||
item.zimFilePath?.let {
|
||||
val currentZimFilePath = zimReaderContainer.zimCanonicalPath
|
||||
val file = File(it)
|
||||
zimReaderContainer.setZimFile(file)
|
||||
if (zimReaderContainer.zimCanonicalPath != currentZimFilePath) {
|
||||
item.zimReaderSource?.toDatabase().let {
|
||||
if (!activity.isCustomApp()) {
|
||||
zimReaderContainer.setZimReaderSource(item.zimReaderSource)
|
||||
}
|
||||
val currentZimReaderSource = zimReaderContainer.zimReaderSource
|
||||
if (zimReaderContainer.zimReaderSource != currentZimReaderSource) {
|
||||
// if current zim file is not the same set the main page of that zim file
|
||||
// so that when we go back it properly loads the article, and do nothing if the
|
||||
// zim file is same because there might be multiple tabs opened.
|
||||
@ -72,7 +73,7 @@ data class ShowOpenNoteDialog(
|
||||
val positions = JSONArray()
|
||||
urls.put(CONTENT_PREFIX + zimReaderContainer.mainPage)
|
||||
positions.put(0)
|
||||
editor.putString(TAG_CURRENT_FILE, zimReaderContainer.zimCanonicalPath)
|
||||
editor.putString(TAG_CURRENT_FILE, zimReaderContainer.zimReaderSource?.toDatabase())
|
||||
editor.putString(TAG_CURRENT_ARTICLES, "$urls")
|
||||
editor.putString(TAG_CURRENT_POSITIONS, "$positions")
|
||||
editor.putInt(TAG_CURRENT_TAB, 0)
|
||||
|
@ -32,8 +32,8 @@ data class OpenPage(
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
activity as CoreMainActivity
|
||||
activity.popNavigationBackstack()
|
||||
if (page.zimFilePath != zimReaderContainer.zimCanonicalPath) {
|
||||
page.zimFilePath?.let { activity.openPage(page.url, it) }
|
||||
if (page.zimReaderSource != zimReaderContainer.zimReaderSource) {
|
||||
page.zimReaderSource?.let { activity.openPage(page.url, it) }
|
||||
} else {
|
||||
activity.openPage(page.url)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import java.io.File
|
||||
class ZimReaderSource(
|
||||
val file: File? = null,
|
||||
val uri: Uri? = null,
|
||||
private val assetFileDescriptorList: List<AssetFileDescriptor>? = null
|
||||
val assetFileDescriptorList: List<AssetFileDescriptor>? = null
|
||||
) {
|
||||
constructor(uri: Uri) : this(
|
||||
uri = uri,
|
||||
|
@ -22,6 +22,7 @@ import android.app.Activity
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.AssetFileDescriptor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
@ -44,6 +45,8 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
|
||||
object FileUtils {
|
||||
@ -476,4 +479,48 @@ object FileUtils {
|
||||
@JvmStatic
|
||||
fun getDemoFilePathForCustomApp(context: Context) =
|
||||
"${ContextCompat.getExternalFilesDirs(context, null)[0]}/demo.zim"
|
||||
|
||||
@SuppressLint("Recycle")
|
||||
@JvmStatic
|
||||
fun getAssetFileDescriptorFromUri(
|
||||
context: Context,
|
||||
uri: Uri
|
||||
): List<AssetFileDescriptor>? {
|
||||
return try {
|
||||
val assetFileDescriptor = context.contentResolver.openAssetFileDescriptor(uri, "r")
|
||||
// Verify whether libkiwix can successfully open this file descriptor or not.
|
||||
return if (
|
||||
isFileDescriptorCanOpenWithLibkiwix(assetFileDescriptor?.parcelFileDescriptor?.fd)
|
||||
) {
|
||||
assetFileDescriptor?.let(::listOf)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (ignore: FileNotFoundException) {
|
||||
null
|
||||
} catch (ignore: Exception) {
|
||||
// It may throw a SecurityException in the Play Store variant
|
||||
// since we have limited access to storage and URIs in the Play Store variant.
|
||||
// If the user opens the ZIM file via app linking and closes the application,
|
||||
// the next time they try to open that ZIM file, we won't have access to this URI.
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isFileDescriptorCanOpenWithLibkiwix(fdNumber: Int?): Boolean {
|
||||
return try {
|
||||
// Attempt to create a FileInputStream object using the specified path.
|
||||
// Since libkiwix utilizes this path to create the archive object internally,
|
||||
// it is crucial to verify if we can successfully read the file descriptor (fd)
|
||||
// via the given file path before passing it to libkiwix.
|
||||
// This precaution helps prevent runtime crashes.
|
||||
// For more details, refer to https://github.com/kiwix/kiwix-android/pull/3636.
|
||||
FileInputStream("dev/fd/$fdNumber")
|
||||
true
|
||||
} catch (ignore: Exception) {
|
||||
ignore.printStackTrace()
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class KiwixServer @Inject constructor(
|
||||
val archive = if (path == getDemoFilePathForCustomApp(context)) {
|
||||
// For custom apps using a demo file, create an Archive with FileDescriptor
|
||||
val assetFileDescriptor =
|
||||
zimReaderContainer.zimFileReader?.assetFileDescriptorList?.get(0)
|
||||
zimReaderContainer.zimReaderSource?.assetFileDescriptorList?.get(0)
|
||||
val startOffset = assetFileDescriptor?.startOffset ?: 0L
|
||||
val size = assetFileDescriptor?.length ?: 0L
|
||||
Archive(
|
||||
|
@ -117,7 +117,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View {
|
||||
.filter(BooksOnDiskListItem::isSelected)
|
||||
.filterIsInstance<BookOnDisk>()
|
||||
.map {
|
||||
it.file.absolutePath
|
||||
it.zimReaderSource.toDatabase()
|
||||
}
|
||||
.onEach { path ->
|
||||
Log.v(tag, "ZIM PATH : $path")
|
||||
@ -487,7 +487,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View {
|
||||
if (it is BookOnDisk) {
|
||||
zimReaderContainer.zimFileReader?.let { zimFileReader ->
|
||||
val booksOnDiskListItem =
|
||||
(BookOnDisk(it.file, zimFileReader) as BooksOnDiskListItem)
|
||||
(BookOnDisk(zimFileReader) as BooksOnDiskListItem)
|
||||
.apply {
|
||||
isSelected = true
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user