new: add loading overlay for WebView widget while pages load
This commit is contained in:
@@ -7,10 +7,14 @@ import androidx.compose.ui.Modifier
|
||||
* Embeds a live web page. Platforms with a native web view (Android, iOS) render the page inline,
|
||||
* honouring [darkTheme] so the page matches the app's light/dark appearance; the others fall back to
|
||||
* [WebViewUnavailable], which offers to open the page in the system browser.
|
||||
*
|
||||
* [onLoadingStateChange] reports whether a page is currently loading, so the caller can show a
|
||||
* loader. Fallback platforms report `false` immediately since there is nothing to load.
|
||||
*/
|
||||
@Composable
|
||||
expect fun PlatformWebView(
|
||||
url: String,
|
||||
darkTheme: Boolean,
|
||||
onLoadingStateChange: (Boolean) -> Unit = {},
|
||||
modifier: Modifier = Modifier,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package bzh.ajaury.chombev.web.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import bzh.ajaury.chombev.theme.ChomBevTheme
|
||||
|
||||
/**
|
||||
* Full-surface loading overlay shown on top of the embedded web view while a page is loading. The
|
||||
* opaque [MaterialTheme.colorScheme.surface] background hides the blank web view until the page is
|
||||
* ready, so the transition reads cleanly in both light and dark themes.
|
||||
*/
|
||||
@Composable
|
||||
internal fun WebViewLoader(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier.background(MaterialTheme.colorScheme.surface),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun WebViewLoaderPreview() {
|
||||
ChomBevTheme {
|
||||
WebViewLoader(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,22 @@
|
||||
package bzh.ajaury.chombev.web.ui
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import bzh.ajaury.chombev.navigation.WebPage
|
||||
|
||||
/**
|
||||
* Displays a [WebPage] inside the app: the embedded page, matching the app's [darkTheme]. The
|
||||
* surrounding top and bottom bars are provided by the app-level scaffold.
|
||||
* Displays a [WebPage] inside the app: the embedded page, matching the app's [darkTheme]. A
|
||||
* [WebViewLoader] covers the page while it loads. The surrounding top and bottom bars are provided by
|
||||
* the app-level scaffold.
|
||||
*/
|
||||
@Composable
|
||||
fun WebViewScreen(
|
||||
@@ -18,11 +24,22 @@ fun WebViewScreen(
|
||||
contentPadding: PaddingValues,
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
) {
|
||||
PlatformWebView(
|
||||
url = page.url,
|
||||
darkTheme = darkTheme,
|
||||
// Start in the loading state; each distinct page loads afresh.
|
||||
var isLoading by remember(page) { mutableStateOf(true) }
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(contentPadding)
|
||||
.fillMaxSize(),
|
||||
)
|
||||
) {
|
||||
PlatformWebView(
|
||||
url = page.url,
|
||||
darkTheme = darkTheme,
|
||||
onLoadingStateChange = { isLoading = it },
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
if (isLoading) {
|
||||
WebViewLoader(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user