Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added file picker in play store variant #3636

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener.Compani
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener.Companion.SCROLL_UP
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BookOnDiskDelegate
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskAdapter
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
Expand All @@ -90,7 +89,6 @@ import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel.FileSelectActions.Req
import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel.FileSelectActions.RequestNavigateTo
import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel.FileSelectActions.RequestSelect
import org.kiwix.kiwixmobile.zimManager.fileselectView.FileSelectListState
import java.io.File
import javax.inject.Inject

private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
Expand Down Expand Up @@ -245,7 +243,7 @@ class LocalLibraryFragment : BaseFragment() {
offerAction(FileSelectActions.UserClickedDownloadBooksButton)
}
}
hideFilePickerButton()
setUpFilePickerButton()

fragmentDestinationLibraryBinding?.zimfilelist?.addOnScrollListener(
SimpleRecyclerViewScrollListener { _, newState ->
Expand Down Expand Up @@ -303,19 +301,9 @@ class LocalLibraryFragment : BaseFragment() {
}
}

private fun hideFilePickerButton() {
if (sharedPreferenceUtil.isPlayStoreBuild) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
fragmentDestinationLibraryBinding?.selectFile?.visibility = View.GONE
}
}

private fun setUpFilePickerButton() {
fragmentDestinationLibraryBinding?.selectFile?.setOnClickListener {
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
showManageExternalStoragePermissionDialog()
} else {
showFileChooser()
}
showFileChooser()
}
}

Expand All @@ -335,40 +323,24 @@ class LocalLibraryFragment : BaseFragment() {
private val fileSelectLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
result.data?.data?.let { uri ->
getZimFileFromUri(uri)?.let(::navigateToReaderFragment)
result.data?.data?.let {
// Taking `takePersistableUriPermission` for uris that user try to open via file picker.
// Since we need access of this uri to open the same file again,
// if user tries to open notes, history etc.
requireActivity().contentResolver.takePersistableUriPermission(
it,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
navigateToReaderFragment(it)
}
}
}

private fun getZimFileFromUri(
uri: Uri
): File? {
val filePath = FileUtils.getLocalFilePathByUri(
requireActivity().applicationContext, uri
private fun navigateToReaderFragment(uri: Uri) {
activity?.navigate(
LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader()
.apply { zimFileUri = "$uri" }
)
if (filePath == null || !File(filePath).exists()) {
activity.toast(R.string.error_file_not_found)
return null
}
val file = File(filePath)
return if (!FileUtils.isValidZimFile(file.path)) {
activity.toast(R.string.error_file_invalid)
null
} else {
file
}
}

private fun navigateToReaderFragment(file: File) {
if (!file.canRead()) {
activity.toast(R.string.unable_to_read_zim_file)
} else {
activity?.navigate(
LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader()
.apply { zimFileUri = file.toUri().toString() }
)
}
}

override fun onResume() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package org.kiwix.kiwixmobile.nav.destination.reader

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
Expand All @@ -33,6 +32,7 @@ import android.view.View.VISIBLE
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toFile
import androidx.core.net.toUri
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
import org.kiwix.kiwixmobile.R
Expand All @@ -43,7 +43,6 @@ import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions.Super
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions.Super.ShouldCall
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.setupDrawerToggle
import org.kiwix.kiwixmobile.core.extensions.coreMainActivity
import org.kiwix.kiwixmobile.core.extensions.isFileExist
import org.kiwix.kiwixmobile.core.extensions.setBottomMarginToFragmentContainerView
import org.kiwix.kiwixmobile.core.extensions.setImageDrawableCompat
import org.kiwix.kiwixmobile.core.extensions.snack
Expand All @@ -55,9 +54,7 @@ import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView
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.FileUtils.getAssetFileDescriptorFromUri
import java.io.File

private const val HIDE_TAB_SWITCHER_DELAY: Long = 300

Expand Down Expand Up @@ -108,15 +105,20 @@ class KiwixReaderFragment : CoreReaderFragment() {
}

private fun tryOpeningZimFile(zimFileUri: String) {
val filePath = FileUtils.getLocalFilePathByUri(
requireActivity().applicationContext, Uri.parse(zimFileUri)
)

if (filePath == null || !File(filePath).isFileExist()) {
activity.toast(R.string.error_file_not_found)
return
getAssetFileDescriptorFromUri(
requireActivity(),
zimFileUri.toUri()
)?.let { assetFileDescriptor ->
openZimFile(
null,
assetFileDescriptor = assetFileDescriptor,
assetFileDescriptorPath = zimFileUri
)
} ?: kotlin.run {
// exit the previous if any loaded
exitBook()
activity.toast(R.string.cannot_open_file)
}
openZimFile(File(filePath))
}

override fun loadDrawerViews() {
Expand All @@ -134,7 +136,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
}

private fun closeZimBook() {
zimReaderContainer?.setZimFile(null)
zimReaderContainer?.setZimFileOrFileDescriptor(null, null, null)
}

override fun openHomeScreen() {
Expand Down Expand Up @@ -205,9 +207,7 @@ class KiwixReaderFragment : CoreReaderFragment() {

override fun onResume() {
super.onResume()
if (zimReaderContainer?.zimFile == null &&
zimReaderContainer?.zimFileReader?.assetFileDescriptor == null
) {
if (zimReaderContainer?.isValidZimFileReader == false) {
exitBook()
}
if (isFullScreenVideo) {
Expand All @@ -226,15 +226,28 @@ class KiwixReaderFragment : CoreReaderFragment() {
currentTab: Int
) {
val settings = requireActivity().getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0)
val zimFile = settings.getString(TAG_CURRENT_FILE, null)

if (zimFile != null && File(zimFile).isFileExist()) {
if (zimReaderContainer?.zimFile == null) {
openZimFile(File(zimFile))
Log.d(
TAG_KIWIX,
"Kiwix normal start, Opened last used zimFile: -> $zimFile"
)
val zimFileUri = settings.getString(TAG_CURRENT_FILE, null)

if (zimFileUri != null &&
getAssetFileDescriptorFromUri(requireActivity(), zimFileUri.toUri()) != null
) {
if (zimReaderContainer?.assetFileDescriptor == null) {
getAssetFileDescriptorFromUri(
requireActivity(),
zimFileUri.toUri()
)?.let { assetFileDescriptor ->
openZimFile(
null,
assetFileDescriptor = assetFileDescriptor,
assetFileDescriptorPath = zimFileUri
)
Log.d(
TAG_KIWIX,
"Kiwix normal start, Opened last used zimFile: -> $zimFileUri"
)
} ?: kotlin.run {
activity.toast(R.string.cannot_open_file)
}
} else {
zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
}
Expand Down Expand Up @@ -299,7 +312,11 @@ class KiwixReaderFragment : CoreReaderFragment() {
// pass this uri to zimFileReader, which is necessary for saving
// notes, bookmarks, history, and reopening the same ZIM file after the app closes.
getAssetFileDescriptorFromUri(activity, it)?.let { assetFileDescriptor ->
openZimFile(null, assetFileDescriptor = assetFileDescriptor, filePath = "$it")
openZimFile(
null,
assetFileDescriptor = assetFileDescriptor,
assetFileDescriptorPath = "$it"
)
} ?: kotlin.run {
activity.toast(R.string.cannot_open_file)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ data class DeleteFiles(private val booksOnDiskListItems: List<BookOnDisk>) :
return fold(true) { acc, book ->
acc && deleteSpecificZimFile(book).also {
if (it && book.file.canonicalPath == zimReaderContainer.zimCanonicalPath) {
zimReaderContainer.setZimFile(null)
zimReaderContainer.setZimFileOrFileDescriptor(null)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ abstract class CoreReaderFragment :
reopenBook()
}
tempWebViewForUndo?.let {
zimReaderContainer?.setZimFile(tempZimFileForUndo)
zimReaderContainer?.setZimFileOrFileDescriptor(tempZimFileForUndo)
webViewList.add(index, it)
tabsAdapter?.notifyDataSetChanged()
snackBarRoot?.let { root ->
Expand Down Expand Up @@ -1479,17 +1479,11 @@ abstract class CoreReaderFragment :
file: File?,
isCustomApp: Boolean = false,
assetFileDescriptor: AssetFileDescriptor? = null,
filePath: String? = null
assetFileDescriptorPath: String? = null
) {
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) || isCustomApp) {
if (file?.isFileExist() == true) {
openAndSetInContainer(file = file)
updateTitle()
} else if (assetFileDescriptor != null) {
openAndSetInContainer(
assetFileDescriptor = assetFileDescriptor,
filePath = filePath
)
if (file?.isFileExist() == true || assetFileDescriptor != null) {
openAndSetInContainer(file = file, assetFileDescriptor, assetFileDescriptorPath)
updateTitle()
} else {
Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + file?.absolutePath)
Expand Down Expand Up @@ -1522,24 +1516,23 @@ abstract class CoreReaderFragment :
private fun openAndSetInContainer(
file: File? = null,
assetFileDescriptor: AssetFileDescriptor? = null,
filePath: String? = null
assetFileDescriptorPath: String? = null
) {
try {
if (isNotPreviouslyOpenZim(file?.canonicalPath)) {
if (isNotPreviouslyOpenZim(file?.canonicalPath) &&
isNotPreviouslyOpenZim(assetFileDescriptorPath)
) {
webViewList.clear()
}
} catch (e: IOException) {
e.printStackTrace()
}
zimReaderContainer?.let { zimReaderContainer ->
if (assetFileDescriptor != null) {
zimReaderContainer.setZimFileDescriptor(
assetFileDescriptor,
filePath = filePath
)
} else {
zimReaderContainer.setZimFile(file)
}
zimReaderContainer.setZimFileOrFileDescriptor(
file,
assetFileDescriptor,
assetFileDescriptorPath
)

val zimFileReader = zimReaderContainer.zimFileReader
zimFileReader?.let { zimFileReader ->
Expand Down Expand Up @@ -1632,7 +1625,7 @@ abstract class CoreReaderFragment :

private fun restoreDeletedTabs() {
if (tempWebViewListForUndo.isNotEmpty()) {
zimReaderContainer?.setZimFile(tempZimFileForUndo)
zimReaderContainer?.setZimFileOrFileDescriptor(tempZimFileForUndo)
webViewList.addAll(tempWebViewListForUndo)
tabsAdapter?.notifyDataSetChanged()
snackBarRoot?.let { root ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ data class BookmarkItem(
) : this(
zimId = zimFileReader.id,
zimName = zimFileReader.name,
zimFilePath = zimFileReader.zimFile?.canonicalPath ?: zimFileReader.assetDescriptorFilePath,
zimFilePath = zimFileReader.zimCanonicalPath,
bookmarkUrl = url,
title = title,
favicon = zimFileReader.favicon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ sealed class HistoryListItem : PageRelated {
) : this(
zimId = zimFileReader.id,
zimName = zimFileReader.name,
zimFilePath = zimFileReader.zimFile?.canonicalPath
?: zimFileReader.assetDescriptorFilePath
?: "",
zimFilePath = zimFileReader.zimCanonicalPath ?: "",
favicon = zimFileReader.favicon,
historyUrl = url,
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ data class NoteListItem(
) : this(
zimId = zimFileReader.id,
title = title,
zimFilePath = zimFileReader.zimFile?.canonicalPath ?: zimFileReader.assetDescriptorFilePath,
zimFilePath = zimFileReader.zimCanonicalPath,
zimUrl = url,
favicon = zimFileReader.favicon,
noteFilePath = noteFilePath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.kiwix.kiwixmobile.core.page.notes.viewmodel.effects

import androidx.appcompat.app.AppCompatActivity
import androidx.core.net.toUri
import io.reactivex.processors.PublishProcessor
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
Expand All @@ -29,7 +30,7 @@ import org.kiwix.kiwixmobile.core.page.viewmodel.effects.OpenPage
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.ShowNoteDialog
import java.io.File
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getAssetFileDescriptorFromUri
import javax.inject.Inject

data class ShowOpenNoteDialog(
Expand All @@ -49,8 +50,19 @@ data class ShowOpenNoteDialog(
// 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 file = File(it)
zimReaderContainer.setZimFile(file)
// Obtain the asset file descriptor for the provided URI.
// Given that we now exclusively use the fileDescriptor for all our functionalities,
// we have modified this method to assign the fileDescriptor instead of the file
// to address the crash triggered when clicking the 'OPEN NOTE' button.
getAssetFileDescriptorFromUri(
activity,
it.toUri()
)?.let { assetFileDescriptor ->
zimReaderContainer.setZimFileOrFileDescriptor(
assetFileDescriptor = assetFileDescriptor,
assetDescriptorFilePath = it
)
}
}
effects.offer(OpenNote(item.noteFilePath, item.zimUrl, item.title))
}
Expand Down
Loading
Loading