diff --git a/web/android/app/src/main/java/ai/omnigent/android/MainActivity.kt b/web/android/app/src/main/java/ai/omnigent/android/MainActivity.kt index d55a0c83c7..b4446de49c 100644 --- a/web/android/app/src/main/java/ai/omnigent/android/MainActivity.kt +++ b/web/android/app/src/main/java/ai/omnigent/android/MainActivity.kt @@ -583,6 +583,7 @@ class MainActivity : AppCompatActivity() { switchButton.getHitRect(hitRect) if (hitRect.height() < minHeight) hitRect.bottom = hitRect.top + minHeight container.touchDelegate = TouchDelegate(hitRect, switchButton) + emitSwitcherHeight() } } @@ -719,6 +720,24 @@ class MainActivity : AppCompatActivity() { webView.evaluateJavascript(js, null) } + /** Push the measured server-switcher pill height into the web layer. */ + private fun emitSwitcherHeight() { + if (!::switchButton.isInitialized || !::webView.isInitialized) return + val height = switchButton.height + if (height <= 0) return + val d = resources.displayMetrics.density + val js = + """ + (() => { + document.documentElement.style.setProperty( + '--omnigent-android-switcher-height', + '${height / d}px' + ); + })(); + """.trimIndent() + webView.evaluateJavascript(js, null) + } + private fun hasPermission(permission: String): Boolean = ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED diff --git a/web/android/app/src/test/java/ai/omnigent/android/MainActivityTest.kt b/web/android/app/src/test/java/ai/omnigent/android/MainActivityTest.kt index 5e3db5cda4..eaf6b88365 100644 --- a/web/android/app/src/test/java/ai/omnigent/android/MainActivityTest.kt +++ b/web/android/app/src/test/java/ai/omnigent/android/MainActivityTest.kt @@ -1,13 +1,16 @@ package ai.omnigent.android +import android.content.Context import android.content.res.Configuration import android.view.View import android.view.ViewGroup +import android.webkit.ValueCallback import android.webkit.WebView import androidx.core.view.WindowInsetsControllerCompat import androidx.test.core.app.ApplicationProvider import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith @@ -118,6 +121,48 @@ class MainActivityTest { assertEquals((48 * density).toInt(), delegate.bounds.height()) } + @Test + fun `switcher layout publishes measured height to the web layer`() { + ServerStore(ApplicationProvider.getApplicationContext()).connect("https://example.com") + val activity = Robolectric.buildActivity(MainActivity::class.java).setup().get() + val pill = activity.switchButton() + val recordingWebView = RecordingWebView(activity) + activity.replaceWebView(recordingWebView) + + val density = activity.resources.displayMetrics.density + val pillHeight = (34 * density).toInt() + pill.layout(100, 40, 220, 40 + pillHeight) + + assertNotNull(recordingWebView.lastScript) + assertTrue( + recordingWebView.lastScript!!.contains( + "--omnigent-android-switcher-height", + ), + ) + assertTrue(recordingWebView.lastScript!!.contains("34.0px")) + } + + private class RecordingWebView( + context: Context, + ) : WebView(context) { + var lastScript: String? = null + + override fun evaluateJavascript( + script: String, + resultCallback: ValueCallback?, + ) { + lastScript = script + } + } + + private fun MainActivity.replaceWebView(webView: WebView) { + MainActivity::class + .java + .getDeclaredField("webView") + .apply { isAccessible = true } + .set(this, webView) + } + private fun MainActivity.switchButton(): View = MainActivity::class .java diff --git a/web/src/index.css b/web/src/index.css index 5855393645..491e3a9fc9 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -162,7 +162,8 @@ --omnigent-bottom-bar-visible: 0; /* web-owned 0|1 */ /* Android floating server-switcher pill footprint (margin + height). Used by the Android scroll-fade gradient so it starts at the pill - bottom. Set once; if the pill size changes, update both values. */ + bottom. Height defaults for older shells; the Android app sets + --omnigent-android-switcher-height from the measured pill after layout. */ --omnigent-android-switcher-margin: 8px; --omnigent-android-switcher-height: 25px; --omnigent-inset-top: var(--omnigent-safe-top);