From d0d1577bfe54bc29632d7be07cfc617220a3caa4 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 22 Jun 2026 19:00:24 -0400 Subject: [PATCH] fix(napplets): remove the stray white band at the bottom of the applet WebView Two edge-to-edge issues on the napplet/nsite host, both surfacing as a white strip below the applet on a light page: - Double bottom inset. The root inset listener turned the system-bar/cutout insets into padding but returned them un-consumed, so the child WebView (which on targetSdk 35+ auto-applies any insets it receives to its web content) padded the bottom a SECOND time. Zero those types before they reach the WebView, keeping IME flowing so keyboard resize still works. - Over-scroll reveal. Forcing a scroll past the content edge stretched the view and exposed the shell document's background behind the applet iframe. WebView.overScrollMode only governs the outer frame, so also inject `overscroll-behavior: none` into the applet document (alongside the shim) to kill the stretch at the source, theme-independently. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../amethyst/napplethost/NappletContentServer.kt | 8 +++++++- .../amethyst/napplethost/NappletHostActivity.kt | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/nappletHost/src/main/kotlin/com/vitorpamplona/amethyst/napplethost/NappletContentServer.kt b/nappletHost/src/main/kotlin/com/vitorpamplona/amethyst/napplethost/NappletContentServer.kt index 360475cd17..0b569af9c4 100644 --- a/nappletHost/src/main/kotlin/com/vitorpamplona/amethyst/napplethost/NappletContentServer.kt +++ b/nappletHost/src/main/kotlin/com/vitorpamplona/amethyst/napplethost/NappletContentServer.kt @@ -169,9 +169,15 @@ class NappletContentServer( /** Inserts the `window.napplet` client shim into the applet's HTML document. */ private fun injectShim(html: ByteArray): ByteArray { val text = html.decodeToString() + // Disable the document's overscroll affordance (the bounce/stretch): the Android-level + // WebView.overScrollMode only governs the outer frame, so an applet whose own root background is + // transparent stretched on over-scroll and exposed the shell's background behind it (a stray + // white band at the bottom). `overscroll-behavior: none` removes the stretch at the source, + // theme-independently. Allowed by the app CSP's `style-src 'unsafe-inline'`. + val style = "" // In website mode, set the NIP-07 flag synchronously *before* the shim so window.nostr installs. val nip07Flag = if (websiteMode) "" else "" - val script = "$nip07Flag" + val script = "$style$nip07Flag" val headIdx = text.indexOf(" - val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()) + val applied = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() + val bars = insets.getInsets(applied) view.setPadding(bars.left, bars.top, bars.right, bars.bottom) - insets + // Zero the insets we just turned into padding before they reach the child WebView: on + // targetSdk 35+ the WebView auto-applies any insets it receives to its own web content, so + // leaving them un-consumed padded the bottom a SECOND time — a band of the page's own + // background above the navigation bar. Keep the other types (notably IME) flowing so the + // applet's keyboard-aware resize still works. + WindowInsetsCompat.Builder(insets).setInsets(applied, Insets.NONE).build() } probeAndMount() @@ -375,6 +382,10 @@ class NappletHostActivity : ComponentActivity() { safeBrowsingEnabled = true } } + // Disable the overscroll stretch/glow: forcing a scroll past the content edge stretched the + // WebView's output and exposed the shell document's background behind the applet iframe at the + // seam (a stray white band at the bottom). The applet's own content still scrolls normally. + webView.overScrollMode = View.OVER_SCROLL_NEVER WebView.setWebContentsDebuggingEnabled(false) webView.webViewClient = NappletWebViewClient() }