new: add offline fallback support for WebView
This commit is contained in:
@@ -23,6 +23,7 @@ import platform.darwin.NSObject
|
||||
@Composable
|
||||
actual fun PlatformWebView(
|
||||
url: String,
|
||||
offlineHtml: String?,
|
||||
darkTheme: Boolean,
|
||||
onLoadingStateChange: (Boolean) -> Unit,
|
||||
modifier: Modifier,
|
||||
@@ -30,6 +31,8 @@ actual fun PlatformWebView(
|
||||
// WKWebView holds its navigationDelegate weakly, so keep a strong reference across recompositions.
|
||||
val navigationDelegate = remember { WebViewNavigationDelegate() }
|
||||
navigationDelegate.onLoadingStateChange = onLoadingStateChange
|
||||
navigationDelegate.offlineHtml = offlineHtml
|
||||
navigationDelegate.baseUrl = url
|
||||
|
||||
UIKitView(
|
||||
modifier = modifier,
|
||||
@@ -54,12 +57,19 @@ actual fun PlatformWebView(
|
||||
|
||||
/**
|
||||
* Forwards WKWebView load lifecycle events to [onLoadingStateChange] so the UI can show a loader
|
||||
* while a page is loading and hide it once loading finishes (or fails).
|
||||
* while a page is loading and hide it once loading finishes.
|
||||
*
|
||||
* When a navigation fails, it swaps in [offlineHtml] (loaded against [baseUrl] so links resolve) so
|
||||
* the page still shows content offline. [showingOffline] guards against re-entering the fallback.
|
||||
*/
|
||||
private class WebViewNavigationDelegate :
|
||||
NSObject(),
|
||||
WKNavigationDelegateProtocol {
|
||||
var onLoadingStateChange: (Boolean) -> Unit = {}
|
||||
var offlineHtml: String? = null
|
||||
var baseUrl: String = ""
|
||||
|
||||
private var showingOffline = false
|
||||
|
||||
override fun webView(
|
||||
webView: WKWebView,
|
||||
@@ -82,7 +92,7 @@ private class WebViewNavigationDelegate :
|
||||
didFailNavigation: WKNavigation?,
|
||||
withError: NSError,
|
||||
) {
|
||||
onLoadingStateChange(false)
|
||||
handleFailure(webView)
|
||||
}
|
||||
|
||||
// Shares the (WKWebView, WKNavigation?, NSError) Kotlin signature with didFailNavigation above.
|
||||
@@ -92,7 +102,17 @@ private class WebViewNavigationDelegate :
|
||||
didFailProvisionalNavigation: WKNavigation?,
|
||||
withError: NSError,
|
||||
) {
|
||||
onLoadingStateChange(false)
|
||||
handleFailure(webView)
|
||||
}
|
||||
|
||||
private fun handleFailure(webView: WKWebView) {
|
||||
val html = offlineHtml
|
||||
if (html != null && !showingOffline) {
|
||||
showingOffline = true
|
||||
webView.loadHTMLString(string = html, baseURL = NSURL.URLWithString(baseUrl))
|
||||
} else {
|
||||
onLoadingStateChange(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user