1
0
mirror of https://github.com/AllanWang/Frost-for-Facebook.git synced 2024-09-19 15:11:42 +02:00

Create hilt web file chooser implementation

This commit is contained in:
Allan Wang 2021-09-25 15:55:07 -07:00
parent 1ac15f84b0
commit 8db1930d76
No known key found for this signature in database
GPG Key ID: 69D90B885D405BDB
6 changed files with 92 additions and 47 deletions

View File

@ -24,14 +24,11 @@ import android.content.res.ColorStateList
import android.graphics.PointF
import android.graphics.drawable.Drawable
import android.graphics.drawable.RippleDrawable
import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.widget.FrameLayout
import android.widget.ImageView
@ -79,10 +76,9 @@ import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.R
import com.pitchedapps.frost.contracts.FileChooserContract
import com.pitchedapps.frost.contracts.FileChooserDelegate
import com.pitchedapps.frost.contracts.MainActivityContract
import com.pitchedapps.frost.contracts.VideoViewHolder
import com.pitchedapps.frost.contracts.WebFileChooser
import com.pitchedapps.frost.databinding.ActivityMainBinding
import com.pitchedapps.frost.databinding.ActivityMainBottomTabsBinding
import com.pitchedapps.frost.databinding.ActivityMainDrawerWrapperBinding
@ -149,7 +145,6 @@ import kotlin.math.abs
abstract class BaseMainActivity :
BaseActivity(),
MainActivityContract,
FileChooserContract by FileChooserDelegate(),
VideoViewHolder,
SearchViewHolder {
@ -167,6 +162,9 @@ abstract class BaseMainActivity :
@Inject
lateinit var genericDao: GenericDao
@Inject
lateinit var webFileChooser: WebFileChooser
interface ActivityMainContentBinding {
val root: View
val toolbar: Toolbar
@ -715,16 +713,9 @@ abstract class BaseMainActivity :
return true
}
override fun openFileChooser(
filePathCallback: ValueCallback<Array<Uri>?>,
fileChooserParams: WebChromeClient.FileChooserParams
) {
openMediaPicker(filePathCallback, fileChooserParams)
}
@SuppressLint("NewApi")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (onActivityResultWeb(requestCode, resultCode, data)) return
if (webFileChooser.onActivityResultWeb(requestCode, resultCode, data)) return
super.onActivityResult(requestCode, resultCode, data)
fun hasRequest(flag: Int) = resultCode and flag > 0

View File

@ -18,12 +18,9 @@ package com.pitchedapps.frost.activities
import android.content.Intent
import android.graphics.PointF
import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.widget.FrameLayout
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
@ -49,11 +46,9 @@ import ca.allanwang.kau.utils.withMainContext
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.pitchedapps.frost.R
import com.pitchedapps.frost.contracts.ActivityContract
import com.pitchedapps.frost.contracts.FileChooserContract
import com.pitchedapps.frost.contracts.FileChooserDelegate
import com.pitchedapps.frost.contracts.FrostContentContainer
import com.pitchedapps.frost.contracts.VideoViewHolder
import com.pitchedapps.frost.contracts.WebFileChooser
import com.pitchedapps.frost.enums.OverlayContext
import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.facebook.FbItem
@ -70,10 +65,12 @@ import com.pitchedapps.frost.utils.frostSnackbar
import com.pitchedapps.frost.views.FrostContentWeb
import com.pitchedapps.frost.views.FrostVideoViewer
import com.pitchedapps.frost.views.FrostWebView
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import javax.inject.Inject
/**
* Created by Allan Wang on 2017-06-01.
@ -155,12 +152,11 @@ class WebOverlayDesktopActivity : WebOverlayActivityBase(USER_AGENT_DESKTOP_CONS
class WebOverlayActivity : WebOverlayActivityBase()
@UseExperimental(ExperimentalCoroutinesApi::class)
@AndroidEntryPoint
abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT) :
BaseActivity(),
ActivityContract,
FrostContentContainer,
VideoViewHolder,
FileChooserContract by FileChooserDelegate() {
VideoViewHolder {
override val frameWrapper: FrameLayout by bindView(R.id.frame_wrapper)
val toolbar: Toolbar by bindView(R.id.overlay_toolbar)
@ -169,6 +165,9 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT
get() = content.coreView
private val coordinator: CoordinatorLayout by bindView(R.id.overlay_main_content)
@Inject
lateinit var webFileChooser: WebFileChooser
private inline val urlTest: String?
get() = intent.getStringExtra(ARG_URL) ?: intent.dataString
@ -297,15 +296,8 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT
kauSwipeOnDestroy()
}
override fun openFileChooser(
filePathCallback: ValueCallback<Array<Uri>?>,
fileChooserParams: WebChromeClient.FileChooserParams
) {
openMediaPicker(filePathCallback, fileChooserParams)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (onActivityResultWeb(requestCode, resultCode, data)) return
if (webFileChooser.onActivityResultWeb(requestCode, resultCode, data)) return
super.onActivityResult(requestCode, resultCode, data)
}

View File

@ -17,18 +17,12 @@
package com.pitchedapps.frost.contracts
import com.mikepenz.iconics.typeface.IIcon
import com.pitchedapps.frost.activities.MainActivity
import com.pitchedapps.frost.fragments.BaseFragment
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BroadcastChannel
/**
* All the contracts for [MainActivity]
*/
interface ActivityContract : FileChooserActivityContract
@UseExperimental(ExperimentalCoroutinesApi::class)
interface MainActivityContract : ActivityContract, MainFabContract {
interface MainActivityContract : MainFabContract {
val fragmentChannel: BroadcastChannel<Int>
val headerBadgeChannel: BroadcastChannel<String>
fun setTitle(res: Int)

View File

@ -26,12 +26,78 @@ import ca.allanwang.kau.permissions.kauRequestPermissions
import ca.allanwang.kau.utils.string
import com.pitchedapps.frost.R
import com.pitchedapps.frost.utils.L
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.scopes.ActivityScoped
import javax.inject.Inject
/**
* Created by Allan Wang on 2017-07-04.
*/
const val MEDIA_CHOOSER_RESULT = 67
interface WebFileChooser {
fun openMediaPicker(
filePathCallback: ValueCallback<Array<Uri>?>,
fileChooserParams: WebChromeClient.FileChooserParams
)
fun onActivityResultWeb(
requestCode: Int,
resultCode: Int,
intent: Intent?
): Boolean
}
class WebFileChooserImpl @Inject internal constructor(private val activity: Activity) :
WebFileChooser {
private var filePathCallback: ValueCallback<Array<Uri>?>? = null
override fun openMediaPicker(
filePathCallback: ValueCallback<Array<Uri>?>,
fileChooserParams: WebChromeClient.FileChooserParams
) {
activity.kauRequestPermissions(PERMISSION_WRITE_EXTERNAL_STORAGE) { granted, _ ->
if (!granted) {
L.d { "Failed to get write permissions" }
filePathCallback.onReceiveValue(null)
return@kauRequestPermissions
}
this.filePathCallback = filePathCallback
val intent = Intent()
intent.type = fileChooserParams.acceptTypes.firstOrNull()
intent.action = Intent.ACTION_GET_CONTENT
activity.startActivityForResult(
Intent.createChooser(intent, activity.string(R.string.pick_image)),
MEDIA_CHOOSER_RESULT
)
}
}
override fun onActivityResultWeb(
requestCode: Int,
resultCode: Int,
intent: Intent?
): Boolean {
L.d { "FileChooser On activity results web $requestCode" }
if (requestCode != MEDIA_CHOOSER_RESULT) return false
val data = intent?.data
filePathCallback?.onReceiveValue(if (data != null) arrayOf(data) else null)
filePathCallback = null
return true
}
}
@Module
@InstallIn(ActivityComponent::class)
interface WebFileChooserModule {
@Binds
@ActivityScoped
fun webFileChooser(to: WebFileChooserImpl): WebFileChooser
}
interface FileChooserActivityContract {
fun openFileChooser(
filePathCallback: ValueCallback<Array<Uri>?>,
@ -59,6 +125,7 @@ class FileChooserDelegate : FileChooserContract {
) {
kauRequestPermissions(PERMISSION_WRITE_EXTERNAL_STORAGE) { granted, _ ->
if (!granted) {
L.d { "Failed to get write permissions" }
filePathCallback.onReceiveValue(null)
return@kauRequestPermissions
}

View File

@ -29,6 +29,7 @@ import ca.allanwang.kau.utils.launchMain
import com.pitchedapps.frost.contracts.FrostContentContainer
import com.pitchedapps.frost.contracts.FrostContentCore
import com.pitchedapps.frost.contracts.FrostContentParent
import com.pitchedapps.frost.contracts.WebFileChooser
import com.pitchedapps.frost.db.CookieDao
import com.pitchedapps.frost.db.currentCookie
import com.pitchedapps.frost.facebook.FB_HOME_URL
@ -69,6 +70,9 @@ class FrostWebView @JvmOverloads constructor(
@Inject
lateinit var themeProvider: ThemeProvider
@Inject
lateinit var webFileChooser: WebFileChooser
@Inject
lateinit var cookieDao: CookieDao
@ -98,7 +102,7 @@ class FrostWebView @JvmOverloads constructor(
// attempt to get custom client; otherwise fallback to original
frostWebClient = (container as? WebFragment)?.client(this) ?: FrostWebViewClient(this)
webViewClient = frostWebClient
webChromeClient = FrostChromeClient(this, themeProvider)
webChromeClient = FrostChromeClient(this, themeProvider, webFileChooser)
addJavascriptInterface(FrostJSI(this), "Frost")
setBackgroundColor(Color.TRANSPARENT)
setDownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->

View File

@ -30,11 +30,9 @@ import ca.allanwang.kau.permissions.kauRequestPermissions
import ca.allanwang.kau.utils.materialDialog
import com.afollestad.materialdialogs.callbacks.onDismiss
import com.afollestad.materialdialogs.input.input
import com.pitchedapps.frost.R
import com.pitchedapps.frost.contracts.ActivityContract
import com.pitchedapps.frost.contracts.WebFileChooser
import com.pitchedapps.frost.injectors.ThemeProvider
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.frostSnackbar
import com.pitchedapps.frost.views.FrostWebView
import kotlinx.coroutines.channels.SendChannel
@ -49,13 +47,13 @@ import kotlinx.coroutines.channels.SendChannel
*/
class FrostChromeClient(
web: FrostWebView,
private val themeProvider: ThemeProvider
private val themeProvider: ThemeProvider,
private val webFileChooser: WebFileChooser,
) : WebChromeClient() {
private val refresh: SendChannel<Boolean> = web.parent.refreshChannel
private val progress: SendChannel<Int> = web.parent.progressChannel
private val title: SendChannel<String> = web.parent.titleChannel
private val activity = (web.context as? ActivityContract)
private val context = web.context!!
override fun getDefaultVideoPoster(): Bitmap? =
@ -83,9 +81,8 @@ class FrostChromeClient(
filePathCallback: ValueCallback<Array<Uri>?>,
fileChooserParams: FileChooserParams
): Boolean {
activity?.openFileChooser(filePathCallback, fileChooserParams)
?: webView.frostSnackbar(R.string.file_chooser_not_found, themeProvider)
return activity != null
webFileChooser.openMediaPicker(filePathCallback, fileChooserParams)
return true
}
private fun JsResult.frostCancel() {