summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-05 02:37:13 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-05 02:37:13 +0200
commitbacab81915a9ab640437b7d674bf9e29e701b1f1 (patch)
tree6864c40bc37746ea065df9545ab74d6775292114
parentee9798fe3b88face2fa34f14874770f509c788a5 (diff)
downloadmeshbay-bacab81915a9ab640437b7d674bf9e29e701b1f1.tar.gz
feat(android): launch icon stays up for at least half a second
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt23
1 files changed, 23 insertions, 0 deletions
diff --git a/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt b/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt
index fc446b9..0fa63d6 100644
--- a/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt
+++ b/packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/MainActivity.kt
@@ -6,9 +6,11 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
+import android.os.SystemClock
import android.util.Log
import android.view.View
import android.view.ViewGroup
+import android.view.ViewTreeObserver
import android.view.WindowInsets
import android.webkit.ConsoleMessage
import android.webkit.PermissionRequest
@@ -66,6 +68,7 @@ class MainActivity : Activity() {
root = FrameLayout(this)
setContentView(root)
applyInsets(root)
+ if (savedInstanceState == null && Build.VERSION.SDK_INT >= 31) holdSplash()
// A WebView too old for the page's crypto would fail at the first
// handshake; say so before loading anything.
@@ -255,6 +258,22 @@ class MainActivity : Activity() {
catch (e: android.content.ActivityNotFoundException) { Log.w(Bridge.TAG, "no browser for $url") }
}
+ /**
+ * Android 12+ shows the launcher icon until the first frame is drawn, which
+ * on a warm process is a flash. Holding that frame keeps it up long enough
+ * to be seen; the WebView loads underneath in the meantime.
+ */
+ private fun holdSplash() {
+ val until = SystemClock.uptimeMillis() + SPLASH_MS
+ root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ if (SystemClock.uptimeMillis() < until) return false
+ root.viewTreeObserver.removeOnPreDrawListener(this)
+ return true
+ }
+ })
+ }
+
/** Edge-to-edge is enforced from Android 15: keep the page clear of the bars and the keyboard. */
private fun applyInsets(view: View) {
view.setOnApplyWindowInsetsListener { v, insets ->
@@ -296,4 +315,8 @@ class MainActivity : Activity() {
if (::web.isInitialized) { root.removeView(web); web.destroy() }
super.onDestroy()
}
+
+ companion object {
+ private const val SPLASH_MS = 500L
+ }
}