Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
) {
Expand Down
2 changes: 1 addition & 1 deletion android-llmservice/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
Loading