Merge remote-tracking branch 'origin/Issue#2868' into Issue#2868

This commit is contained in:
MohitMaliFtechiz 2022-06-23 11:08:57 +05:30
commit c780e1a67d
4 changed files with 112 additions and 37 deletions

View File

@ -18,8 +18,10 @@
package org.kiwix.kiwixmobile.core.main;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.webkit.WebResourceRequest;
@ -27,9 +29,12 @@ import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import java.io.File;
import java.util.HashMap;
import org.kiwix.kiwixmobile.core.CoreApp;
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.utils.files.FileUtils;
import static org.kiwix.kiwixmobile.core.reader.ZimFileReader.CONTENT_PREFIX;
import static org.kiwix.kiwixmobile.core.reader.ZimFileReader.UI_URI;
@ -97,11 +102,22 @@ public class CoreWebViewClient extends WebViewClient {
private boolean handleEpubAndPdf(String url) {
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (DOCUMENT_TYPES.containsKey(extension)) {
File savedFile = FileUtils.downloadFileFromUrl(url, null, zimReaderContainer);
if (savedFile != null && savedFile.exists()) {
Context context = CoreApp.getInstance();
Uri uri = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
? FileProvider.getUriForFile(
context,
context.getPackageName() + ".fileprovider", savedFile)
: Uri.fromFile(savedFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(url);
intent.setDataAndType(uri, DOCUMENT_TYPES.get(extension));
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
callback.openExternalUrl(intent);
}
return true;
}
return false;

View File

@ -20,12 +20,9 @@ package org.kiwix.kiwixmobile.core.main
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.Environment
import android.os.Handler
import android.os.Message
import android.util.AttributeSet
import android.util.Log
import android.view.ContextMenu
import android.view.View
import android.view.ViewGroup
@ -40,8 +37,7 @@ import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.getCurrentLocale
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import java.io.File
import java.io.IOException
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
import javax.inject.Inject
private const val INITIAL_SCALE = 100
@ -147,39 +143,16 @@ open class KiwixWebView @SuppressLint("SetJavaScriptEnabled") constructor(
internal class SaveHandler(private val zimReaderContainer: ZimReaderContainer) :
Handler() {
private fun getDecodedFileName(url: String?, src: String?): String =
url?.substringAfterLast("/", "")
?.takeIf { it.contains(".") }
?: src?.substringAfterLast("/", "")
?.substringAfterLast("%3A") ?: ""
@SuppressWarnings("NestedBlockDepth")
override fun handleMessage(msg: Message) {
val url = msg.data["url"] as? String
val src = msg.data["src"] as? String
if (url != null || src != null) {
val fileName = getDecodedFileName(url, src)
var root =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
if (instance.externalMediaDirs.isNotEmpty()) {
root = instance.externalMediaDirs[0]
}
val fileToSave = sequence {
yield(File(root, fileName))
yieldAll(
generateSequence(1) { it + 1 }.map {
File(root, fileName.replace(".", "_$it."))
}
)
}.first { !it.exists() }
val source = Uri.parse(src)
try {
zimReaderContainer.load("$source", emptyMap()).data.use { inputStream ->
fileToSave.outputStream().use { inputStream.copyTo(it) }
}
instance.toast(instance.getString(R.string.save_media_saved, fileToSave.name))
} catch (e: IOException) {
Log.w("kiwix", "Couldn't save image", e)
val savedFile = FileUtils.downloadFileFromUrl(url, src, zimReaderContainer)
savedFile?.let {
instance.toast(instance.getString(R.string.save_media_saved, it.name))
} ?: run {
instance.toast(R.string.save_media_error)
}
}

View File

@ -28,11 +28,13 @@ import android.provider.DocumentsContract
import android.util.Log
import android.widget.Toast
import androidx.documentfile.provider.DocumentFile
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.downloader.ChunkUtils
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
import org.kiwix.kiwixmobile.core.extensions.get
import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import java.io.BufferedReader
import java.io.File
import java.io.IOException
@ -288,4 +290,48 @@ object FileUtils {
}
return null
}
/**
* Returns the file name from the url or src. In url it gets the file name from the last '/' and
* if it contains '.'. If the url is null then it'll get the file name from the last '/'.
* If the url and src doesn't exist it returns the empty string.
*/
fun getDecodedFileName(url: String?, src: String?): String =
url?.substringAfterLast("/", "")
?.takeIf { it.contains(".") }
?: src?.substringAfterLast("/", "")
?.substringAfterLast("%3A") ?: ""
@JvmStatic fun downloadFileFromUrl(
url: String?,
src: String?,
zimReaderContainer: ZimReaderContainer
): File? {
val fileName = getDecodedFileName(url, src)
var root =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
if (CoreApp.instance.externalMediaDirs.isNotEmpty()) {
root = CoreApp.instance.externalMediaDirs[0]
}
val fileToSave = sequence {
yield(File(root, fileName))
yieldAll(
generateSequence(1) { it + 1 }.map {
File(
root, fileName.replace(".", "_$it.")
)
}
)
}.first { !it.exists() }
val source = if (url == null) Uri.parse(src) else Uri.parse(url)
return try {
zimReaderContainer.load("$source", emptyMap()).data.use { inputStream ->
fileToSave.outputStream().use { inputStream.copyTo(it) }
}
fileToSave
} catch (e: IOException) {
Log.w("kiwix", "Couldn't save file", e)
null
}
}
}

View File

@ -88,4 +88,44 @@ class FileUtilsTest {
every { mockFile.path } returns "$fileName$extension"
every { mockFile.exists() } returns fileExists
}
@Test
fun `test decode file name`() {
val fileName =
FileUtils.getDecodedFileName(
url = "https://kiwix.org/contributors/contributors_list.pdf",
src = null
)
assertThat(fileName).isEqualTo("contributors_list.pdf")
}
@Test
fun `test file name if extension doesn't exist`() {
val fileName = FileUtils.getDecodedFileName(url = "https://kiwix.org/contributors/", src = null)
assertThat(fileName).isEqualTo("")
}
@Test
fun `test file name if the url and src doesn't exist`() {
val fileName = FileUtils.getDecodedFileName(url = null, src = null)
assertThat(fileName).isEqualTo("")
}
@Test
fun `test file name if only file name exist`() {
val fileName = FileUtils.getDecodedFileName(src = "android_tutorials.pdf", url = null)
assertThat(fileName).isEqualTo("")
}
@Test
fun `test file name if url doesn't exist`() {
val fileName = FileUtils.getDecodedFileName(url = null, src = "/html/images/test.png")
assertThat(fileName).isEqualTo("test.png")
}
@Test
fun `test file name if url and src's extension doesn't exist`() {
val fileName = FileUtils.getDecodedFileName(url = null, src = "/html/images/")
assertThat(fileName).isEqualTo("")
}
}