@@ -59,6 +59,7 @@ import androidx.compose.material3.OutlinedTextField
59import androidx.compose.material3.Scaffold
59import androidx.compose.material3.Scaffold
60import androidx.compose.material3.Surface
60import androidx.compose.material3.Surface
61import androidx.compose.material3.Text
61import androidx.compose.material3.Text
62+import androidx.compose.material3.TextButton
62import androidx.compose.material3.TopAppBar
63import androidx.compose.material3.TopAppBar
63import androidx.compose.runtime.Composable
64import androidx.compose.runtime.Composable
64import androidx.compose.runtime.LaunchedEffect
65import androidx.compose.runtime.LaunchedEffect
@@ -72,6 +73,7 @@ import androidx.compose.ui.Alignment
72import androidx.compose.ui.Modifier
73import androidx.compose.ui.Modifier
73import androidx.compose.ui.draw.clip
74import androidx.compose.ui.draw.clip
74import androidx.compose.ui.hapticfeedback.HapticFeedbackType
75import androidx.compose.ui.hapticfeedback.HapticFeedbackType
76+import androidx.compose.ui.platform.LocalClipboardManager
75import androidx.compose.ui.platform.LocalContext
77import androidx.compose.ui.platform.LocalContext
76import androidx.compose.ui.platform.LocalDensity
78import androidx.compose.ui.platform.LocalDensity
77import androidx.compose.ui.platform.LocalHapticFeedback
79import androidx.compose.ui.platform.LocalHapticFeedback
@@ -455,9 +457,13 @@ private fun ChatInputBar(
455 onStop: () -> Unit,
457 onStop: () -> Unit,
457 val haptic = LocalHapticFeedback.current
459 val haptic = LocalHapticFeedback.current
460+ val clipboardManager = LocalClipboardManager.current
458 Surface(tonalElevation = 3.dp) {
461 Surface(tonalElevation = 3.dp) {
460 modifier = Modifier.fillMaxWidth().imePadding().padding(horizontal = 12.dp, vertical = 8.dp),
463 modifier = Modifier.fillMaxWidth().imePadding().padding(horizontal = 12.dp, vertical = 8.dp),
466+ modifier = Modifier.fillMaxWidth(),
461 verticalAlignment = Alignment.Bottom,
467 verticalAlignment = Alignment.Bottom,
462 horizontalArrangement = Arrangement.spacedBy(8.dp),
468 horizontalArrangement = Arrangement.spacedBy(8.dp),
@@ -468,6 +474,24 @@ private fun ChatInputBar(
468 enabled = !loading,
474 enabled = !loading,
469 placeholder = { Text("Message opencode…") },
475 placeholder = { Text("Message opencode…") },
470 maxLines = 5,
476 maxLines = 5,
477+ // Offer a quick way to wipe the draft once there's something to clear
478+ // and we're not mid-generation (where the field is a poor place to fuss).
479+ trailingIcon = if (draft.isNotEmpty() && !generating) {
482+ onClick = { onDraftChange("") },
483+ modifier = Modifier.size(20.dp),
487+ contentDescription = "Clear draft",
488+ modifier = Modifier.size(16.dp),
471 // Surface a running count once the draft gets long, so the user has a
495 // Surface a running count once the draft gets long, so the user has a
472 // sense of scale before sending a wall of text.
496 // sense of scale before sending a wall of text.
473 supportingText = if (draft.length > 500) {
497 supportingText = if (draft.length > 500) {
@@ -510,5 +534,17 @@ private fun ChatInputBar(
537+ // With nothing typed yet, offer a one-tap way to drop in clipboard contents.
538+ if (draft.isEmpty() && !generating && !loading) {
541+ clipboardManager.getText()?.text?.let { onDraftChange(it) }
543+ contentPadding = PaddingValues(0.dp),