diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt
index 4b118dd79..0f9e9d5ff 100644
--- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt
+++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt
@@ -52,6 +52,7 @@ import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
+import org.kiwix.kiwixmobile.core.utils.files.FileUtils
import org.kiwix.kiwixmobile.main.KiwixMainActivity
import org.kiwix.kiwixmobile.zimManager.Fat32Checker
import org.kiwix.kiwixmobile.zimManager.Fat32Checker.Companion.FOUR_GIGABYTES_IN_KILOBYTES
@@ -405,6 +406,9 @@ class CopyMoveFileHandler @Inject constructor(
}
}
+ suspend fun isValidZimFile(destinationFile: File): Boolean =
+ FileUtils.isSplittedZimFile(destinationFile.name) || validateZimFileValid(destinationFile)
+
fun handleInvalidZimFile(destinationFile: File, sourceUri: Uri) {
val errorMessage = activity.getString(R.string.error_file_invalid)
if (isMoveOperation) {
@@ -428,7 +432,7 @@ class CopyMoveFileHandler @Inject constructor(
}
}
- suspend fun isValidZimFile(destinationFile: File): Boolean {
+ private suspend fun validateZimFileValid(destinationFile: File): Boolean {
var archive: Archive? = null
return try {
// create archive object, and check if it has the mainEntry or not to validate the ZIM file.
diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt
index 013211f74..51d8875dc 100644
--- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt
+++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/LocalLibraryFragment.kt
@@ -93,6 +93,7 @@ import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener.Compani
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.utils.files.FileUtils.isSplittedZimFile
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
@@ -422,7 +423,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
// If the file name is not found, then let them to copy the file
// and we will handle this later.
val fileName = documentFile?.name
- if (fileName != null && !FileUtils.isValidZimFile(fileName)) {
+ if (fileName != null && !isValidZimFile(fileName)) {
activity.toast(string.error_file_invalid)
return@launch
}
@@ -439,6 +440,9 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
}
}
+ private fun isValidZimFile(fileName: String): Boolean =
+ FileUtils.isValidZimFile(fileName) || FileUtils.isSplittedZimFile(fileName)
+
private suspend fun getZimFileFromUri(
uri: Uri
): File? {
@@ -633,11 +637,11 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
!shouldShowRationalePermission()
override fun onFileCopied(file: File) {
- navigateToReaderFragment(file = file)
+ validateAndOpenZimInReader(file)
}
override fun onFileMoved(file: File) {
- navigateToReaderFragment(file = file)
+ validateAndOpenZimInReader(file)
}
override fun onError(errorMessage: String) {
@@ -694,4 +698,16 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
copyMoveFileHandler?.copyMoveZIMFileInSelectedStorage(storageDevice)
}
}
+
+ private fun validateAndOpenZimInReader(file: File) {
+ if (isSplittedZimFile(file.path)) {
+ showWarningDialogForSplittedZimFile()
+ } else {
+ navigateToReaderFragment(file = file)
+ }
+ }
+
+ private fun showWarningDialogForSplittedZimFile() {
+ dialogShower.show(KiwixDialog.ShowWarningAboutSplittedZimFile)
+ }
}
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt
index 7bf1861cd..39201be07 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/dialog/KiwixDialog.kt
@@ -118,6 +118,14 @@ sealed class KiwixDialog(
cancelable = false
)
+ data object ShowWarningAboutSplittedZimFile : KiwixDialog(
+ R.string.verify_zim_chunk_dialog_title,
+ R.string.verify_zim_chunks_dialog_message,
+ android.R.string.ok,
+ null,
+ cancelable = false
+ )
+
object SaveOrOpenUnsupportedFiles : KiwixDialog(
R.string.save_or_open_unsupported_files_dialog_title,
R.string.save_or_open_unsupported_files_dialog_message,
diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt
index b4d482946..d4f437357 100644
--- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt
+++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/files/FileUtils.kt
@@ -489,6 +489,19 @@ object FileUtils {
fun isValidZimFile(filePath: String): Boolean =
filePath.endsWith(".zim") || filePath.endsWith(".zimaa")
+ /**
+ * Determines whether the given file path corresponds to a split ZIM file.
+ *
+ * A split ZIM file has an extension that starts with ".zima" followed by a single character,
+ * such as ".zimaa", ".zimab", etc. This method checks if the file path ends with this specific pattern.
+ *
+ * @param filePath The file path to evaluate.
+ * @return `true` if the file path corresponds to a split ZIM file, `false` otherwise.
+ */
+ @JvmStatic
+ fun isSplittedZimFile(filePath: String): Boolean =
+ filePath.matches(Regex(".*\\.zima.$"))
+
/**
* Get the main storage path for a given storage name (SD card or USB stick).
*
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 9721e4e00..995cc2e12 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -334,6 +334,8 @@
Moving ZIM file…
Kiwix requires the ZIM file to be in its own data directory. Do you want to copy or move it there?
Error in copying the ZIM file: %s.
+ Be cautious: Ensure all ZIM chunks have been properly moved/copied!
+ You can verify them inside “Android/media/org.kiwix…/” folder.\nOnce done, refresh the library screen by swiping down. The split ZIM file will then appear in your library.
Why copy/move files to app public directory?
Due to Google Play policies on Android 11 and above, our app can no longer directly access files stored elsewhere on your device. To let you view your selected files, we need to move or copy them into a special folder within our application directory. This allows us to access and open the files.
Choose storage to copy/move ZIM file