Merge pull request #4310 from vitorpamplona/claude/relaxed-ride-ixt1q1

Move load progress from ProgressBar to BrowserChromeHost pill
This commit is contained in:
Vitor Pamplona
2026-10-02 11:19:01 -04:00
committed by GitHub
2 changed files with 7 additions and 49 deletions
@@ -27,7 +27,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
@@ -142,10 +141,6 @@ class NappletBrowserActivity : ComponentActivity() {
// The pill, find, console and page dialogs — the shared Compose chrome (see BrowserChromeHost). // The pill, find, console and page dialogs — the shared Compose chrome (see BrowserChromeHost).
private var chrome: BrowserChromeHost? = null private var chrome: BrowserChromeHost? = null
// A thin determinate progress bar pinned to the top edge (browser-style), driven by the chrome
// client's onProgressChanged; hidden at 100%.
private val topProgressBar by lazy { buildTopProgressBar() }
// The NIP-07 shim + browser extras, injected at document start in this window and in its popups. // The NIP-07 shim + browser extras, injected at document start in this window and in its popups.
private var shimJs: String = "" private var shimJs: String = ""
@@ -348,8 +343,6 @@ class NappletBrowserActivity : ComponentActivity() {
} }
this.root = root this.root = root
chrome = buildChrome().also { it.attach(root) } chrome = buildChrome().also { it.attach(root) }
// Added last so the thin loading bar paints above the content (and over the grabber's top edge).
root.addView(topProgressBar)
setContentView(root) setContentView(root)
// Pad by the system bars + cutout AND the IME: on an edge-to-edge window (enforced for targetSdk // Pad by the system bars + cutout AND the IME: on an edge-to-edge window (enforced for targetSdk
// 35+ on Android 15+) windowSoftInputMode=adjustResize no longer shrinks the window, so without // 35+ on Android 15+) windowSoftInputMode=adjustResize no longer shrinks the window, so without
@@ -1840,26 +1833,13 @@ class NappletBrowserActivity : ComponentActivity() {
} }
/** /**
* A thin determinate progress bar pinned to the top edge, like a browser's. Driven by * Feeds the page's load progress to the pill, which draws it under the grabber (and as a ring around
* [BrowserChromeClient.onProgressChanged]: visible while the page loads and gone at 100%. * Stop when open); cleared at 100%.
*/ */
private fun buildTopProgressBar(): ProgressBar =
ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal).apply {
max = 100
isIndeterminate = false
visibility = View.GONE
progressTintList = ColorStateList.valueOf(resolveThemeColor(android.R.attr.colorPrimary))
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dp(3), Gravity.TOP)
}
/** Shows the thin top bar at [progress]% while loading, hiding it once the page is fully loaded. */
private fun updateLoadProgress(progress: Int) { private fun updateLoadProgress(progress: Int) {
if (progress >= 100) { if (progress >= 100) {
topProgressBar.visibility = View.GONE
updateUi { copy(loadProgress = null, chrome = chrome.copy(isLoading = false)) } updateUi { copy(loadProgress = null, chrome = chrome.copy(isLoading = false)) }
} else { } else {
topProgressBar.progress = progress
topProgressBar.visibility = View.VISIBLE
updateUi { copy(loadProgress = progress / 100f) } updateUi { copy(loadProgress = progress / 100f) }
} }
} }
@@ -24,7 +24,6 @@ import android.annotation.SuppressLint
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.content.res.ColorStateList
import android.content.res.Configuration import android.content.res.Configuration
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@@ -198,10 +197,6 @@ class NappletHostActivity : ComponentActivity() {
// first paint, so there's never a blank/dark gap between the index probe and the shell's first frame. // first paint, so there's never a blank/dark gap between the index probe and the shell's first frame.
private var loadingView: View? = null private var loadingView: View? = null
// A thin determinate progress bar pinned to the top edge (browser-style), driven by the
// WebChromeClient's onProgressChanged; hidden at 100%.
private val topProgressBar by lazy { buildTopProgressBar() }
// The trusted pull-down pill, find and the developer console — the shared Compose chrome. // The trusted pull-down pill, find and the developer console — the shared Compose chrome.
private var chrome: BrowserChromeHost? = null private var chrome: BrowserChromeHost? = null
@@ -354,9 +349,6 @@ class NappletHostActivity : ComponentActivity() {
addView(contentFrame, FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)) addView(contentFrame, FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT))
} }
chrome = buildChrome().also { it.attach(root) } chrome = buildChrome().also { it.attach(root) }
// Added last so the thin loading bar paints above the content (and over the grabber's top edge); it's
// GONE except while loading, so it never obscures the trusted chrome.
root.addView(topProgressBar)
setContentView(root) setContentView(root)
// Activities are edge-to-edge by default on recent Android; pad by the system bar, display-cutout // Activities are edge-to-edge by default on recent Android; pad by the system bar, display-cutout
// and IME insets so neither the chrome nor the applet draws under the system bars or the soft // and IME insets so neither the chrome nor the applet draws under the system bars or the soft
@@ -736,7 +728,7 @@ class NappletHostActivity : ComponentActivity() {
} }
} }
/** Drives the top loading bar, opens the file picker, and forwards `console.*` output to the panel. */ /** Feeds load progress to the pill, opens the file picker, and forwards `console.*` output to the panel. */
private inner class NappletWebChromeClient : WebChromeClient() { private inner class NappletWebChromeClient : WebChromeClient() {
/** /**
* Without this override WebView's base implementation returns false and shows no picker at all, so * Without this override WebView's base implementation returns false and shows no picker at all, so
@@ -784,14 +776,14 @@ class NappletHostActivity : ComponentActivity() {
return true return true
} }
/** Shows the thin top bar at [progress]% while loading, hiding it once the page is fully loaded. */ /**
* Feeds the page's load progress to the pill, which draws it under the grabber (and as a ring around
* Stop when open); cleared at 100%.
*/
private fun updateLoadProgress(progress: Int) { private fun updateLoadProgress(progress: Int) {
if (progress >= 100) { if (progress >= 100) {
topProgressBar.visibility = View.GONE
chrome?.let { it.ui = it.ui.copy(loadProgress = null, chrome = it.ui.chrome.copy(isLoading = false)) } chrome?.let { it.ui = it.ui.copy(loadProgress = null, chrome = it.ui.chrome.copy(isLoading = false)) }
} else { } else {
topProgressBar.progress = progress
topProgressBar.visibility = View.VISIBLE
chrome?.let { it.ui = it.ui.copy(loadProgress = progress / 100f, chrome = it.ui.chrome.copy(isLoading = true)) } chrome?.let { it.ui = it.ui.copy(loadProgress = progress / 100f, chrome = it.ui.chrome.copy(isLoading = true)) }
} }
} }
@@ -1082,20 +1074,6 @@ class NappletHostActivity : ComponentActivity() {
if (brokerMessenger != null) sendToBroker(msg) if (brokerMessenger != null) sendToBroker(msg)
} }
/**
* A thin determinate progress bar pinned to the top edge, like a browser's. Driven by
* [NappletWebChromeClient.onProgressChanged]: visible while the shell + verified blobs load and gone
* at 100%, so a slow load (e.g. a large bundle over Tor) shows progress instead of a blank dark WebView.
*/
private fun buildTopProgressBar(): ProgressBar =
ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal).apply {
max = 100
isIndeterminate = false
visibility = View.GONE
progressTintList = ColorStateList.valueOf(resolveThemeColor(android.R.attr.colorPrimary))
layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dp(3), Gravity.TOP)
}
/** Persists the new routing choice in the main process, then relaunches this screen to apply it. */ /** Persists the new routing choice in the main process, then relaunches this screen to apply it. */
private fun setNetworkMode(newUseTor: Boolean) { private fun setNetworkMode(newUseTor: Boolean) {
val msg = val msg =