Skip to content

Commit

Permalink
Merge pull request #182 from coderforlife/factory
Browse files Browse the repository at this point in the history
Expose several internal fields and add factory functions
  • Loading branch information
KevinnZou authored Jul 6, 2024
2 parents c40e880 + 07502be commit 4cfc74e
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 99 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ The complete API of this library is as follows:
* navigation from outside the composable.
* @param onCreated Called when the WebView is first created.
* @param onDispose Called when the WebView is destroyed.
* @param factory A function that creates a platform-specific WebView object.
* @sample sample.BasicWebViewSample
*/
@Composable
Expand All @@ -563,8 +564,10 @@ fun WebView(
modifier: Modifier = Modifier,
captureBackPresses: Boolean = true,
navigator: WebViewNavigator = rememberWebViewNavigator(),
onCreated: () -> Unit = {},
onDispose: () -> Unit = {},
webViewJsBridge: WebViewJsBridge? = null,
onCreated: (NativeWebView) -> Unit = {},
onDispose: (NativeWebView) -> Unit = {},
factory: ((WebViewFactoryParam) -> NativeWebView)? = null,
)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import kotlinx.serialization.json.Json
* Created By Kevin Zou On 2023/9/5
*/

actual typealias NativeWebView = WebView

/**
* Android implementation of [IWebView]
*/
class AndroidWebView(
private val webView: WebView,
override val webView: WebView,
override val scope: CoroutineScope,
override val webViewJsBridge: WebViewJsBridge?,
) : IWebView {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.multiplatform.webview.web

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.multiplatform.webview.jsbridge.WebViewJsBridge
Expand All @@ -14,16 +15,24 @@ actual fun ActualWebView(
captureBackPresses: Boolean,
navigator: WebViewNavigator,
webViewJsBridge: WebViewJsBridge?,
onCreated: () -> Unit,
onDispose: () -> Unit,
onCreated: (NativeWebView) -> Unit,
onDispose: (NativeWebView) -> Unit,
factory: (WebViewFactoryParam) -> NativeWebView,
) {
AccompanistWebView(
state,
modifier,
captureBackPresses,
navigator,
webViewJsBridge,
onCreated = { _ -> onCreated() },
onDispose = { _ -> onDispose() },
onCreated = onCreated,
onDispose = onDispose,
factory = { factory(WebViewFactoryParam(it)) },
)
}

/** Android WebView factory parameters: a context. */
actual data class WebViewFactoryParam(val context: Context)

/** Default WebView factory for Android. */
actual fun defaultWebViewFactory(param: WebViewFactoryParam) = android.webkit.WebView(param.context)
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi
* Created By Kevin Zou On 2023/9/5
*/

expect class NativeWebView

/**
* Interface for WebView
*/
interface IWebView {
/**
* The native web view instance. On Android, this is an instance of [android.webkit.WebView].
* On iOS, this is an instance of [WKWebView]. On desktop, this is an instance of [KCEFBrowser].
*/
val webView: NativeWebView

val scope: CoroutineScope

val webViewJsBridge: WebViewJsBridge?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import com.multiplatform.webview.util.KLogger
import com.multiplatform.webview.util.getPlatform
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.merge
import org.jetbrains.compose.resources.ExperimentalResourceApi

/**
* Created By Kevin Zou On 2023/8/31
*/

/**
*
* A wrapper around the Android View WebView to provide a basic WebView composable.
* Provides a basic WebView composable.
* This version of the function is provided for backwards compatibility by using the older
* onCreated and onDispose callbacks and is missing the factory parameter.
*
* @param state The webview state holder where the Uri to load is defined.
* @param modifier A compose modifier
Expand All @@ -30,7 +30,6 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi
* @param onDispose Called when the WebView is destroyed.
* @sample sample.BasicWebViewSample
*/
@OptIn(ExperimentalResourceApi::class)
@Composable
fun WebView(
state: WebViewState,
Expand All @@ -40,6 +39,42 @@ fun WebView(
webViewJsBridge: WebViewJsBridge? = null,
onCreated: () -> Unit = {},
onDispose: () -> Unit = {},
) {
WebView(
state = state,
modifier = modifier,
captureBackPresses = captureBackPresses,
navigator = navigator,
webViewJsBridge = webViewJsBridge,
onCreated = { _ -> onCreated() },
onDispose = { _ -> onDispose() },
)
}

/**
* Provides a basic WebView composable.
*
* @param state The webview state holder where the Uri to load is defined.
* @param modifier A compose modifier
* @param captureBackPresses Set to true to have this Composable capture back presses and navigate
* the WebView back.
* @param navigator An optional navigator object that can be used to control the WebView's
* navigation from outside the composable.
* @param onCreated Called when the WebView is first created.
* @param onDispose Called when the WebView is destroyed.
* @param factory A function that creates a platform-specific WebView object.
* @sample sample.BasicWebViewSample
*/
@Composable
fun WebView(
state: WebViewState,
modifier: Modifier = Modifier,
captureBackPresses: Boolean = true,
navigator: WebViewNavigator = rememberWebViewNavigator(),
webViewJsBridge: WebViewJsBridge? = null,
onCreated: (NativeWebView) -> Unit = {},
onDispose: (NativeWebView) -> Unit = {},
factory: ((WebViewFactoryParam) -> NativeWebView)? = null,
) {
val webView = state.webView

Expand Down Expand Up @@ -119,6 +154,7 @@ fun WebView(
webViewJsBridge = webViewJsBridge,
onCreated = onCreated,
onDispose = onDispose,
factory = factory ?: ::defaultWebViewFactory,
)

DisposableEffect(Unit) {
Expand All @@ -131,6 +167,24 @@ fun WebView(
}
}

/**
* Platform specific parameters given to the WebView factory function. This is a
* data class containing one or more platform-specific values necessary to
* create a platform-specific WebView:
* - On Android, this contains a `Context` object
* - On iOS, this contains a `WKWebViewConfiguration` object created from the
* provided WebSettings
* - On Desktop, this contains the WebViewState, the KCEFClient, and the
* loaded file content (if a file, otherwise, an empty string)
*/
expect class WebViewFactoryParam

/**
* Platform specific default WebView factory function. This can be called from
* a custom factory function for any platforms that don't need to be customized.
*/
expect fun defaultWebViewFactory(param: WebViewFactoryParam): NativeWebView

/**
* Expect API of [WebView] that is implemented in the platform-specific modules.
*/
Expand All @@ -141,6 +195,7 @@ expect fun ActualWebView(
captureBackPresses: Boolean = true,
navigator: WebViewNavigator = rememberWebViewNavigator(),
webViewJsBridge: WebViewJsBridge? = null,
onCreated: () -> Unit = {},
onDispose: () -> Unit = {},
onCreated: (NativeWebView) -> Unit = {},
onDispose: (NativeWebView) -> Unit = {},
factory: (WebViewFactoryParam) -> NativeWebView = ::defaultWebViewFactory,
)
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ class WebViewState(webContent: WebContent) {
*/
internal var webView by mutableStateOf<IWebView?>(null)

/**
* The native web view instance. On Android, this is an instance of [android.webkit.WebView].
* On iOS, this is an instance of [WKWebView]. On desktop, this is an instance of [KCEFBrowser].
*/
val nativeWebView get() = webView?.webView ?: error("WebView is not initialized")

/**
* The saved view state from when the view was destroyed last. To restore state,
* use the navigator and only call loadUrl if the bundle is null.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import org.cef.network.CefPostData
import org.cef.network.CefPostDataElement
import org.cef.network.CefRequest

actual typealias NativeWebView = KCEFBrowser

/**
* Created By Kevin Zou On 2023/9/12
*/
class DesktopWebView(
private val webView: KCEFBrowser,
override val webView: KCEFBrowser,
override val scope: CoroutineScope,
override val webViewJsBridge: WebViewJsBridge?,
) : IWebView {
Expand Down
Loading

0 comments on commit 4cfc74e

Please sign in to comment.