diff --git a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt index 09d09e2c9..e7228a542 100644 --- a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt +++ b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt @@ -8,6 +8,10 @@ import android.webkit.WebViewClient import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.viewinterop.AndroidView import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -15,9 +19,10 @@ import kotlinx.coroutines.flow.onEach @SuppressLint("SetJavaScriptEnabled") @Composable actual fun CustomWebView( - navigator: WebViewNavigator, - modifier: Modifier, url: String, + modifier: Modifier, + navigator: WebViewNavigator, + scrollConnection: NestedScrollConnection?, ) { var webView: WebView? = null @@ -29,6 +34,7 @@ actual fun CustomWebView( }.launchIn(this) } + val density = LocalDensity.current.density AndroidView( modifier = modifier, factory = { context -> @@ -44,7 +50,17 @@ actual fun CustomWebView( } settings.javaScriptEnabled = true + setOnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY -> + scrollConnection?.onPreScroll( + available = Offset( + x = (oldScrollX - scrollX) / density, + y = (oldScrollY - scrollY) / density, + ), source = NestedScrollSource.Drag + ) + } + loadUrl(url) + webView = this } }, diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt index fe0d88879..e94af911e 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt @@ -2,10 +2,12 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection @Composable expect fun CustomWebView( - navigator: WebViewNavigator = rememberWebViewNavigator(), - modifier: Modifier = Modifier, url: String, + modifier: Modifier = Modifier, + navigator: WebViewNavigator = rememberWebViewNavigator(), + scrollConnection: NestedScrollConnection? = null, ) diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/web/WebViewScreen.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/web/WebViewScreen.kt index 4d199744f..aa823a187 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/web/WebViewScreen.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/web/WebViewScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.remember @@ -28,10 +29,12 @@ class WebViewScreen( @Composable override fun Content() { val navigator = remember { getNavigationCoordinator().getRootNavigator() } + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() Scaffold( topBar = { TopAppBar( title = {}, + scrollBehavior = scrollBehavior, navigationIcon = { Image( modifier = Modifier.onClick { @@ -68,6 +71,7 @@ class WebViewScreen( CustomWebView( modifier = Modifier.fillMaxSize(), navigator = webNavigator, + scrollConnection = scrollBehavior.nestedScrollConnection, url = url, ) } diff --git a/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt b/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt index 3528f4bb9..b3ab4e116 100644 --- a/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt +++ b/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CustomWebView.kt @@ -2,12 +2,23 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +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 androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.interop.UIKitView +import androidx.compose.ui.platform.LocalDensity import kotlinx.cinterop.readValue +import kotlinx.cinterop.useContents import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import platform.CoreGraphics.CGRectZero +import platform.UIKit.UIScrollView +import platform.UIKit.UIScrollViewDelegateProtocol import platform.WebKit.WKNavigation import platform.WebKit.WKNavigationDelegateProtocol import platform.WebKit.WKWebView @@ -16,9 +27,10 @@ import platform.darwin.NSObject @Composable actual fun CustomWebView( - navigator: WebViewNavigator, - modifier: Modifier, url: String, + modifier: Modifier, + navigator: WebViewNavigator, + scrollConnection: NestedScrollConnection?, ) { var webView: WKWebView? = null @@ -30,6 +42,10 @@ actual fun CustomWebView( }.launchIn(this) } + val density = LocalDensity.current.density + var lastOffsetX by remember { mutableStateOf(0f) } + var lastOffsetY by remember { mutableStateOf(0f) } + UIKitView( factory = { val config = WKWebViewConfiguration().apply { @@ -42,7 +58,6 @@ actual fun CustomWebView( userInteractionEnabled = true allowsBackForwardNavigationGestures = true val navigationDelegate = object : NSObject(), WKNavigationDelegateProtocol { - override fun webView( webView: WKWebView, didFinishNavigation: WKNavigation?, @@ -51,6 +66,21 @@ actual fun CustomWebView( } } this.navigationDelegate = navigationDelegate + this.scrollView.delegate = object : NSObject(), UIScrollViewDelegateProtocol { + override fun scrollViewDidScroll(scrollView: UIScrollView) { + scrollView.contentOffset.useContents { + val offsetX = (lastOffsetX - x).toFloat() / density + val offsetY = (lastOffsetY - y).toFloat() / density + scrollConnection?.onPreScroll( + available = Offset(offsetX, offsetY), + source = NestedScrollSource.Drag, + ) + lastOffsetX = x.toFloat() + lastOffsetY = y.toFloat() + } + } + } + }.also { webView = it }