From 839162007791a881c92900a17e26afdcb7a2b79e Mon Sep 17 00:00:00 2001
From: Claude <noreply@anthropic.com>
Date: Fri, 10 Jul 2026 07:01:19 +0000
Subject: [PATCH] fix(android-llmservice): keep the log strip above the system
 navigation bar (edge-to-edge insets)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

On Android 15 (targetSdk 35) the app is edge-to-edge by default, so the
bottom log strip was drawn behind the system navigation bar (back/home/
recents) and got covered. Enable edge-to-edge explicitly on every version
(consistent inset reporting) and pad the log strip's content above the
navigation bar via navigationBarsPadding — the Surface background still
fills to the screen edge, but the icon+text sit above the nav bar and stay
visible. requirements.md R7.1 updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HTS5FpMtBLJENTGoRUrp5m
---
 .../net/ladenthin/android/llmservice/MainActivity.kt     | 9 +++++++++
 android-llmservice/requirements.md                       | 2 +-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/android-llmservice/app/src/main/kotlin/net/ladenthin/android/llmservice/MainActivity.kt b/android-llmservice/app/src/main/kotlin/net/ladenthin/android/llmservice/MainActivity.kt
index 84add02f..d49d84b3 100644
--- a/android-llmservice/app/src/main/kotlin/net/ladenthin/android/llmservice/MainActivity.kt
+++ b/android-llmservice/app/src/main/kotlin/net/ladenthin/android/llmservice/MainActivity.kt
@@ -11,6 +11,7 @@ import android.provider.OpenableColumns
 import android.widget.Toast
 import androidx.activity.compose.rememberLauncherForActivityResult
 import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
@@ -25,6 +26,7 @@ import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.navigationBarsPadding
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
@@ -84,6 +86,10 @@ class MainActivity : AppCompatActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
+        // Edge-to-edge is forced on Android 15 (targetSdk 35); enable it explicitly on every version
+        // so window-inset handling is consistent. The bottom log strip then pads itself above the
+        // system navigation bar (see LogStrip) instead of being drawn behind it.
+        enableEdgeToEdge()
 
         // Test / automation hook: preload a model straight from an absolute path, bypassing the
         // interactive SAF picker (a separate system process the UI test can't drive). The shipping
@@ -233,8 +239,11 @@ private fun LogStrip(viewModel: ChatViewModel, onOpen: () -> Unit) {
     val log by viewModel.log.collectAsStateWithLifecycle()
     val last = log.lastOrNull() ?: stringResource(R.string.log_empty)
     Surface(tonalElevation = 2.dp) {
+        // navigationBarsPadding keeps the strip's content above the system nav bar (back / home /
+        // recents) under edge-to-edge; the Surface background still fills to the screen edge behind it.
         Row(
             modifier = Modifier.fillMaxWidth().clickable(onClick = onOpen).testTag("logStrip")
+                .navigationBarsPadding()
                 .padding(horizontal = 12.dp, vertical = 6.dp),
             verticalAlignment = Alignment.CenterVertically,
         ) {
diff --git a/android-llmservice/requirements.md b/android-llmservice/requirements.md
index 5edf3b19..ae6edca8 100644
--- a/android-llmservice/requirements.md
+++ b/android-llmservice/requirements.md
@@ -94,7 +94,7 @@ by hand only (no automated test); `build` = enforced at build/resource-compile t
 
 | ID | Requirement | Source | Verified by |
 |---|---|---|---|
-| R7.1 | An **always-visible one-line log strip** sits at the very bottom (🧾, small font, may wrap to 2 display lines) showing the newest log line, or an empty-state string. | `MainActivity.LogStrip` | manual |
+| R7.1 | An **always-visible one-line log strip** sits at the very bottom (🧾, small font, may wrap to 2 display lines) showing the newest log line, or an empty-state string. Under edge-to-edge (`enableEdgeToEdge`) its content is padded **above the system navigation bar** (`navigationBarsPadding`) so it is never covered by the back/home/recents bar. | `MainActivity.onCreate`; `MainActivity.LogStrip` | manual |
 | R7.2 | Tapping the strip opens a **full-screen log viewer** with **Copy all**, **Save as…** (writes a `.txt` via SAF `CreateDocument`), and **Clear**; ✕ (top-right) closes it. | `MainActivity.LogDialog` | manual |
 | R7.3 | The log is a **rolling buffer capped at 500 lines**, each entry prefixed with a local wall-clock time. | `ChatViewModel.log` (`MAX_LOG_LINES`) | manual |
 | R7.4 | Logged events include: model loading/ready/load-failure, generation start (with the effective sampling knobs), reply-complete (char count), generation-stopped, generation-failure, regenerate, chat-cleared, settings-reset, and session save/load. | `ChatViewModel` (`log(...)` call sites) | manual |
