mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-10 07:48:30 -04:00
Merge pull request #3738 from kiwix/Fix#3737
Fixed: Some EPUB files are not downloading.
This commit is contained in:
commit
f17e3f948d
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.webkit.WebResourceResponse
|
||||||
|
import android.widget.Toast
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.justRun
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.slot
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.UnsupportedMimeTypeHandler
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class UnsupportedMimeTypeHandlerTest {
|
||||||
|
private val demoUrl = "content://demoPdf.pdf"
|
||||||
|
private val demoFileName = "demoPdf.pdf"
|
||||||
|
private val sharedPreferenceUtil: SharedPreferenceUtil = mockk()
|
||||||
|
private val zimReaderContainer: ZimReaderContainer = mockk()
|
||||||
|
private val alertDialogShower: AlertDialogShower = mockk(relaxed = true)
|
||||||
|
private val savedFile: File = mockk(relaxed = true)
|
||||||
|
private val activity: Activity = mockk()
|
||||||
|
private val webResourceResponse: WebResourceResponse = mockk()
|
||||||
|
private val inputStream: InputStream = mockk()
|
||||||
|
private val unsupportedMimeTypeHandler = UnsupportedMimeTypeHandler(
|
||||||
|
activity,
|
||||||
|
sharedPreferenceUtil,
|
||||||
|
alertDialogShower,
|
||||||
|
zimReaderContainer
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun before() {
|
||||||
|
every { savedFile.name } returns demoFileName
|
||||||
|
every { sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove() } returns true
|
||||||
|
every { inputStream.read(array()) } returns 1024
|
||||||
|
every { webResourceResponse.data } returns inputStream
|
||||||
|
every {
|
||||||
|
zimReaderContainer.load(
|
||||||
|
demoUrl,
|
||||||
|
emptyMap()
|
||||||
|
)
|
||||||
|
} returns webResourceResponse
|
||||||
|
every { activity.packageManager } returns mockk()
|
||||||
|
every { activity.packageName } returns "org.kiwix.kiwixmobile"
|
||||||
|
every {
|
||||||
|
activity.getString(
|
||||||
|
R.string.save_media_saved,
|
||||||
|
demoFileName
|
||||||
|
)
|
||||||
|
} returns "Saved media as $demoFileName to Downloads/org.kiwix…/"
|
||||||
|
every { savedFile.path } returns "Emulated/0/Downloads/$demoFileName"
|
||||||
|
every { savedFile.exists() } returns true
|
||||||
|
unsupportedMimeTypeHandler.intent = mockk()
|
||||||
|
every { unsupportedMimeTypeHandler.intent.setDataAndType(any(), any()) } returns mockk()
|
||||||
|
every { unsupportedMimeTypeHandler.intent.setFlags(any()) } returns mockk()
|
||||||
|
every { unsupportedMimeTypeHandler.intent.addFlags(any()) } returns mockk()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOpeningFileInExternalReaderApplication() {
|
||||||
|
every {
|
||||||
|
unsupportedMimeTypeHandler.intent.resolveActivity(activity.packageManager)
|
||||||
|
} returns mockk()
|
||||||
|
every { activity.startActivity(unsupportedMimeTypeHandler.intent) } returns mockk()
|
||||||
|
val lambdaSlot = slot<() -> Unit>()
|
||||||
|
unsupportedMimeTypeHandler.showSaveOrOpenUnsupportedFilesDialog(demoUrl, "application/pdf")
|
||||||
|
verify {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
capture(lambdaSlot),
|
||||||
|
any(),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
lambdaSlot.captured.invoke()
|
||||||
|
verify {
|
||||||
|
activity.startActivity(unsupportedMimeTypeHandler.intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOpeningFileWhenNoReaderApplicationInstalled() {
|
||||||
|
every {
|
||||||
|
unsupportedMimeTypeHandler.intent.resolveActivity(activity.packageManager)
|
||||||
|
} returns null
|
||||||
|
mockkStatic(Toast::class)
|
||||||
|
justRun {
|
||||||
|
Toast.makeText(activity, R.string.no_reader_application_installed, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
val lambdaSlot = slot<() -> Unit>()
|
||||||
|
unsupportedMimeTypeHandler.showSaveOrOpenUnsupportedFilesDialog(demoUrl, "application/pdf")
|
||||||
|
verify {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
capture(lambdaSlot),
|
||||||
|
any(),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
lambdaSlot.captured.invoke()
|
||||||
|
verify { activity.toast(R.string.no_reader_application_installed) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFileSavedSuccessfully() {
|
||||||
|
val toastMessage = activity.getString(R.string.save_media_saved, savedFile.name)
|
||||||
|
mockkStatic(Toast::class)
|
||||||
|
justRun {
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
toastMessage,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
val lambdaSlot = slot<() -> Unit>()
|
||||||
|
unsupportedMimeTypeHandler.showSaveOrOpenUnsupportedFilesDialog(
|
||||||
|
demoUrl,
|
||||||
|
"application/pdf"
|
||||||
|
)
|
||||||
|
verify {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
any(),
|
||||||
|
capture(lambdaSlot),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
lambdaSlot.captured.invoke()
|
||||||
|
verify { activity.toast(toastMessage) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUserClicksOnNoThanksButton() {
|
||||||
|
val lambdaSlot = slot<() -> Unit>()
|
||||||
|
unsupportedMimeTypeHandler.showSaveOrOpenUnsupportedFilesDialog(demoUrl, "application/pdf")
|
||||||
|
verify {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
capture(lambdaSlot)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
lambdaSlot.captured.invoke()
|
||||||
|
verify(exactly = 0) { activity.startActivity(any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIfSavingFailed() {
|
||||||
|
val downloadOrOpenEpubAndPdfHandler = UnsupportedMimeTypeHandler(
|
||||||
|
activity,
|
||||||
|
sharedPreferenceUtil,
|
||||||
|
alertDialogShower,
|
||||||
|
zimReaderContainer
|
||||||
|
)
|
||||||
|
mockkStatic(Toast::class)
|
||||||
|
justRun {
|
||||||
|
Toast.makeText(activity, R.string.save_media_error, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
val lambdaSlot = slot<() -> Unit>()
|
||||||
|
downloadOrOpenEpubAndPdfHandler.showSaveOrOpenUnsupportedFilesDialog(null, "application/pdf")
|
||||||
|
verify {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
any(),
|
||||||
|
capture(lambdaSlot),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
lambdaSlot.captured.invoke()
|
||||||
|
verify { activity.toast(R.string.save_media_error) }
|
||||||
|
}
|
||||||
|
}
|
@ -260,6 +260,14 @@ class FileUtilsInstrumentationTest {
|
|||||||
DummyUrlData(
|
DummyUrlData(
|
||||||
"https://kiwix.org/contributors/images/wikipedia",
|
"https://kiwix.org/contributors/images/wikipedia",
|
||||||
null
|
null
|
||||||
|
),
|
||||||
|
DummyUrlData(
|
||||||
|
"https://kiwix.org/contributors/images/wikipedia:hello.epub",
|
||||||
|
"wikipediahello.epub"
|
||||||
|
),
|
||||||
|
DummyUrlData(
|
||||||
|
"https://kiwix.org/contributors/Y Gododin: A Poem of the Battle: of Cattraeth.9842.epub",
|
||||||
|
"Y Gododin A Poem of the Battle of Cattraeth.9842.epub"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
dummyUrlArray.forEach {
|
dummyUrlArray.forEach {
|
||||||
|
@ -243,7 +243,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
|||||||
override fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView {
|
override fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView {
|
||||||
return ToolbarScrollingKiwixWebView(
|
return ToolbarScrollingKiwixWebView(
|
||||||
requireContext(), this, attrs!!, activityMainRoot as ViewGroup, videoView!!,
|
requireContext(), this, attrs!!, activityMainRoot as ViewGroup, videoView!!,
|
||||||
CoreWebViewClient(this, zimReaderContainer!!, sharedPreferenceUtil!!),
|
CoreWebViewClient(this, zimReaderContainer!!),
|
||||||
toolbarContainer!!, bottomToolbar!!, sharedPreferenceUtil = sharedPreferenceUtil!!,
|
toolbarContainer!!, bottomToolbar!!, sharedPreferenceUtil = sharedPreferenceUtil!!,
|
||||||
parentNavigationBar = requireActivity().findViewById(R.id.bottom_nav_view)
|
parentNavigationBar = requireActivity().findViewById(R.id.bottom_nav_view)
|
||||||
)
|
)
|
||||||
|
@ -39,6 +39,12 @@
|
|||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="http" />
|
<data android:scheme="http" />
|
||||||
</intent>
|
</intent>
|
||||||
|
<!-- To open PDF files in external application -->
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<data android:mimeType="application/pdf" />
|
||||||
|
</intent>
|
||||||
|
<!-- To open EPUB files in external application -->
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<data android:mimeType="application/pdf" />
|
<data android:mimeType="application/pdf" />
|
||||||
|
@ -156,6 +156,7 @@ import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED_NEW_TAB
|
|||||||
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
||||||
import org.kiwix.kiwixmobile.core.utils.UpdateUtils.reformatProviderUrl
|
import org.kiwix.kiwixmobile.core.utils.UpdateUtils.reformatProviderUrl
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.UnsupportedMimeTypeHandler
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.deleteCachedFiles
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.deleteCachedFiles
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.readFile
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.readFile
|
||||||
@ -321,6 +322,10 @@ abstract class CoreReaderFragment :
|
|||||||
@JvmField
|
@JvmField
|
||||||
@Inject
|
@Inject
|
||||||
var externalLinkOpener: ExternalLinkOpener? = null
|
var externalLinkOpener: ExternalLinkOpener? = null
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Inject
|
||||||
|
var unsupportedMimeTypeHandler: UnsupportedMimeTypeHandler? = null
|
||||||
private var hideBackToTopTimer: CountDownTimer? = null
|
private var hideBackToTopTimer: CountDownTimer? = null
|
||||||
private var documentSections: MutableList<DocumentSection>? = null
|
private var documentSections: MutableList<DocumentSection>? = null
|
||||||
private var isBackToTopEnabled = false
|
private var isBackToTopEnabled = false
|
||||||
@ -1214,7 +1219,7 @@ abstract class CoreReaderFragment :
|
|||||||
return if (activityMainRoot != null) {
|
return if (activityMainRoot != null) {
|
||||||
ToolbarScrollingKiwixWebView(
|
ToolbarScrollingKiwixWebView(
|
||||||
requireActivity(), this, attrs!!, (activityMainRoot as ViewGroup?)!!, videoView!!,
|
requireActivity(), this, attrs!!, (activityMainRoot as ViewGroup?)!!, videoView!!,
|
||||||
CoreWebViewClient(this, zimReaderContainer!!, sharedPreferenceUtil!!),
|
CoreWebViewClient(this, zimReaderContainer!!),
|
||||||
toolbarContainer!!, bottomToolbar!!,
|
toolbarContainer!!, bottomToolbar!!,
|
||||||
sharedPreferenceUtil!!
|
sharedPreferenceUtil!!
|
||||||
)
|
)
|
||||||
@ -1542,6 +1547,10 @@ abstract class CoreReaderFragment :
|
|||||||
externalLinkOpener?.openExternalUrl(intent)
|
externalLinkOpener?.openExternalUrl(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showSaveOrOpenUnsupportedFilesDialog(url: String, documentType: String?) {
|
||||||
|
unsupportedMimeTypeHandler?.showSaveOrOpenUnsupportedFilesDialog(url, documentType)
|
||||||
|
}
|
||||||
|
|
||||||
protected fun openZimFile(
|
protected fun openZimFile(
|
||||||
file: File?,
|
file: File?,
|
||||||
isCustomApp: Boolean = false,
|
isCustomApp: Boolean = false,
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.main
|
package org.kiwix.kiwixmobile.core.main
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.Log
|
import org.kiwix.kiwixmobile.core.utils.files.Log
|
||||||
@ -27,18 +26,14 @@ import android.webkit.WebResourceRequest
|
|||||||
import android.webkit.WebResourceResponse
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
|
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
|
||||||
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.downloadFileFromUrl
|
|
||||||
|
|
||||||
open class CoreWebViewClient(
|
open class CoreWebViewClient(
|
||||||
protected val callback: WebViewCallback,
|
protected val callback: WebViewCallback,
|
||||||
protected val zimReaderContainer: ZimReaderContainer,
|
protected val zimReaderContainer: ZimReaderContainer
|
||||||
private val sharedPreferenceUtil: SharedPreferenceUtil
|
|
||||||
) : WebViewClient() {
|
) : WebViewClient() {
|
||||||
private var urlWithAnchor: String? = null
|
private var urlWithAnchor: String? = null
|
||||||
|
|
||||||
@ -49,14 +44,14 @@ open class CoreWebViewClient(
|
|||||||
url = convertLegacyUrl(url)
|
url = convertLegacyUrl(url)
|
||||||
urlWithAnchor = if (url.contains("#")) url else null
|
urlWithAnchor = if (url.contains("#")) url else null
|
||||||
if (zimReaderContainer.isRedirect(url)) {
|
if (zimReaderContainer.isRedirect(url)) {
|
||||||
if (handleEpubAndPdf(url)) {
|
if (handleUnsupportedFiles(url)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
view.loadUrl(zimReaderContainer.getRedirect(url))
|
view.loadUrl(zimReaderContainer.getRedirect(url))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (url.startsWith(ZimFileReader.CONTENT_PREFIX)) {
|
if (url.startsWith(ZimFileReader.CONTENT_PREFIX)) {
|
||||||
return handleEpubAndPdf(url)
|
return handleUnsupportedFiles(url)
|
||||||
}
|
}
|
||||||
if (url.startsWith("javascript:")) {
|
if (url.startsWith("javascript:")) {
|
||||||
// Allow javascript for HTML functions and code execution (EX: night mode)
|
// Allow javascript for HTML functions and code execution (EX: night mode)
|
||||||
@ -82,29 +77,10 @@ open class CoreWebViewClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NestedBlockDepth")
|
@Suppress("NestedBlockDepth")
|
||||||
private fun handleEpubAndPdf(url: String): Boolean {
|
private fun handleUnsupportedFiles(url: String): Boolean {
|
||||||
val extension = MimeTypeMap.getFileExtensionFromUrl(url)
|
val extension = MimeTypeMap.getFileExtensionFromUrl(url)
|
||||||
if (DOCUMENT_TYPES.containsKey(extension)) {
|
if (DOCUMENT_TYPES.containsKey(extension)) {
|
||||||
downloadFileFromUrl(
|
callback.showSaveOrOpenUnsupportedFilesDialog(url, DOCUMENT_TYPES[extension])
|
||||||
url,
|
|
||||||
null,
|
|
||||||
zimReaderContainer,
|
|
||||||
sharedPreferenceUtil
|
|
||||||
)?.let {
|
|
||||||
if (it.exists()) {
|
|
||||||
val context: Context = instance
|
|
||||||
val uri = FileProvider.getUriForFile(
|
|
||||||
context,
|
|
||||||
context.packageName + ".fileprovider", it
|
|
||||||
)
|
|
||||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
|
||||||
setDataAndType(uri, DOCUMENT_TYPES[extension])
|
|
||||||
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
|
||||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
||||||
}
|
|
||||||
callback.openExternalUrl(intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -25,6 +25,7 @@ interface WebViewCallback {
|
|||||||
fun webViewUrlFinishedLoading()
|
fun webViewUrlFinishedLoading()
|
||||||
fun webViewFailedLoading(failingUrl: String)
|
fun webViewFailedLoading(failingUrl: String)
|
||||||
fun openExternalUrl(intent: Intent)
|
fun openExternalUrl(intent: Intent)
|
||||||
|
fun showSaveOrOpenUnsupportedFilesDialog(url: String, documentType: String?)
|
||||||
fun webViewProgressChanged(progress: Int, webView: WebView)
|
fun webViewProgressChanged(progress: Int, webView: WebView)
|
||||||
fun webViewTitleUpdated(title: String)
|
fun webViewTitleUpdated(title: String)
|
||||||
fun webViewPageChanged(page: Int, maxPages: Int)
|
fun webViewPageChanged(page: Int, maxPages: Int)
|
||||||
|
@ -108,6 +108,14 @@ sealed class KiwixDialog(
|
|||||||
cancelable = false
|
cancelable = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
object SaveOrOpenUnsupportedFiles : KiwixDialog(
|
||||||
|
R.string.save_or_open_unsupported_files_dialog_title,
|
||||||
|
R.string.save_or_open_unsupported_files_dialog_message,
|
||||||
|
R.string.open,
|
||||||
|
R.string.save,
|
||||||
|
neutralMessage = R.string.no_thanks
|
||||||
|
)
|
||||||
|
|
||||||
data class ShowHotspotDetails(override val args: List<Any>) :
|
data class ShowHotspotDetails(override val args: List<Any>) :
|
||||||
KiwixDialog(
|
KiwixDialog(
|
||||||
R.string.hotspot_turned_on,
|
R.string.hotspot_turned_on,
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.utils.dialog
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.downloadFileFromUrl
|
||||||
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class UnsupportedMimeTypeHandler @Inject constructor(
|
||||||
|
private val activity: Activity,
|
||||||
|
private val sharedPreferenceUtil: SharedPreferenceUtil,
|
||||||
|
private val alertDialogShower: AlertDialogShower,
|
||||||
|
private val zimReaderContainer: ZimReaderContainer
|
||||||
|
) {
|
||||||
|
var intent: Intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
|
||||||
|
fun showSaveOrOpenUnsupportedFilesDialog(url: String?, documentType: String?) {
|
||||||
|
alertDialogShower.show(
|
||||||
|
KiwixDialog.SaveOrOpenUnsupportedFiles,
|
||||||
|
{ openOrSaveFile(url, documentType, true) },
|
||||||
|
{ openOrSaveFile(url, documentType, false) },
|
||||||
|
{ }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openOrSaveFile(url: String?, documentType: String?, openFile: Boolean) {
|
||||||
|
downloadFileFromUrl(
|
||||||
|
url,
|
||||||
|
null,
|
||||||
|
zimReaderContainer,
|
||||||
|
sharedPreferenceUtil
|
||||||
|
)?.let { savedFile ->
|
||||||
|
if (openFile) {
|
||||||
|
openFile(savedFile, documentType)
|
||||||
|
} else {
|
||||||
|
activity.toast(activity.getString(R.string.save_media_saved, savedFile.name)).also {
|
||||||
|
Log.e("DownloadOrOpenEpubAndPdf", "File downloaded at = ${savedFile.path}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
activity.toast(R.string.save_media_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openFile(savedFile: File, documentType: String?) {
|
||||||
|
if (savedFile.exists()) {
|
||||||
|
val uri = FileProvider.getUriForFile(
|
||||||
|
activity,
|
||||||
|
"${activity.packageName}.fileprovider",
|
||||||
|
savedFile
|
||||||
|
)
|
||||||
|
intent.apply {
|
||||||
|
setDataAndType(uri, documentType)
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
||||||
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
}
|
||||||
|
if (intent.resolveActivity(activity.packageManager) != null) {
|
||||||
|
activity.startActivity(intent)
|
||||||
|
} else {
|
||||||
|
activity.toast(R.string.no_reader_application_installed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -410,12 +410,15 @@ object FileUtils {
|
|||||||
|
|
||||||
* We are placing a condition here for if the file name does not have a .bin extension,
|
* We are placing a condition here for if the file name does not have a .bin extension,
|
||||||
then it returns the original file name.
|
then it returns the original file name.
|
||||||
|
* Remove colon if any contains in the fileName since most of the fileSystem
|
||||||
|
will not allow to create file which contains colon in it.
|
||||||
|
see https://github.com/kiwix/kiwix-android/issues/3737
|
||||||
*/
|
*/
|
||||||
fun getDecodedFileName(url: String?): String? {
|
fun getDecodedFileName(url: String?): String? {
|
||||||
var fileName: String? = null
|
var fileName: String? = null
|
||||||
val decodedFileName = URLUtil.guessFileName(url, null, null)
|
val decodedFileName = URLUtil.guessFileName(url, null, null)
|
||||||
if (!decodedFileName.endsWith(".bin")) {
|
if (!decodedFileName.endsWith(".bin")) {
|
||||||
fileName = decodedFileName
|
fileName = decodedFileName.replace(":", "")
|
||||||
}
|
}
|
||||||
return fileName
|
return fileName
|
||||||
}
|
}
|
||||||
@ -444,17 +447,8 @@ object FileUtils {
|
|||||||
)
|
)
|
||||||
if (!root.isFileExist()) root.mkdir()
|
if (!root.isFileExist()) root.mkdir()
|
||||||
}
|
}
|
||||||
if (File(root, fileName).isFileExist()) return File(root, fileName)
|
val fileToSave = File(root, fileName)
|
||||||
val fileToSave = sequence {
|
if (fileToSave.isFileExist()) return fileToSave
|
||||||
yield(File(root, fileName))
|
|
||||||
yieldAll(
|
|
||||||
generateSequence(1) { it + 1 }.map {
|
|
||||||
File(
|
|
||||||
root, fileName.replace(".", "_$it.")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.first { !it.isFileExist() }
|
|
||||||
val source = if (url == null) Uri.parse(src) else Uri.parse(url)
|
val source = if (url == null) Uri.parse(src) else Uri.parse(url)
|
||||||
return try {
|
return try {
|
||||||
zimReaderContainer.load("$source", emptyMap()).data.use { inputStream ->
|
zimReaderContainer.load("$source", emptyMap()).data.use { inputStream ->
|
||||||
|
@ -373,4 +373,6 @@
|
|||||||
<string name="zim_file_content_description">ZIM file which has the reading content</string>
|
<string name="zim_file_content_description">ZIM file which has the reading content</string>
|
||||||
<string name="select_language_content_description">Selecting this language will prioritize displaying downloadable books in that language at the top.</string>
|
<string name="select_language_content_description">Selecting this language will prioritize displaying downloadable books in that language at the top.</string>
|
||||||
<string name="toolbar_back_button_content_description">Go to previous screen</string>
|
<string name="toolbar_back_button_content_description">Go to previous screen</string>
|
||||||
|
<string name="save_or_open_unsupported_files_dialog_title">Save or Open this file?</string>
|
||||||
|
<string name="save_or_open_unsupported_files_dialog_message">Choosing Open will open this file in external reader application.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user