Read a timeout in units, share one usage answer, and let a tilde mean home
The composer's settings row is outlined bubbles opening round menus, and the message box is a TextFieldValue so anything put into it without being typed -- a draft, a share, a slash command -- leaves the cursor at the end. A tap that puts a text selection away no longer also collapses the card the text was drawn in: every open and close on the session screen goes through one guard that spends such a press on the selection. The usage bar and the usage dialog were two polls of one measurement and disagreed for up to a minute at a time; they are one feed now, and the countdown rounds up to the minute in the one place both read. A working directory typed as ~/repos/ai-app was four literal characters on the local transport and as an argument on both, so the existence check refused every home-relative path. It is checked by entering the directory now, expanded for a local spawn the way the remote shell expands it, and stored short so the phone draws what somebody would write. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2970a6cf9a
commit
32b2a4871a
16 files changed
+414
-99
No files matched your search
@@ -0,0 +1,54 @@
|
||||
package com.example.aiapp
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
// The composer's row of settings and pickers, and the menus they open. One file because the
|
||||
// outline and the corner are one appearance: a control shaped like this opens a surface shaped
|
||||
// like this, and a reader learns the pair once.
|
||||
|
||||
/**
|
||||
* A bordered pill: a control that can be seen without being pressed.
|
||||
*
|
||||
* The composer's row -- attach, model, permission mode -- was text buttons, which draw nothing at
|
||||
* all until they are touched. Three bare words sitting under the message field read as a caption
|
||||
* about the field rather than as three things to press, and the only way to find out otherwise was
|
||||
* to press one. The outline says "control" without the weight of a filled button, which is reserved
|
||||
* here for the two that act on the session (send, and start/stop).
|
||||
*/
|
||||
@Composable
|
||||
fun BubbleButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
OutlinedButton(
|
||||
onClick = onClick,
|
||||
enabled = enabled,
|
||||
shape = BubbleShape,
|
||||
// A text button's padding rather than a filled button's 24dp: these sit three across
|
||||
// under the message field, and the wider padding is what decides whether the row fits.
|
||||
contentPadding = ButtonDefaults.TextButtonContentPadding,
|
||||
modifier = modifier,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
/** Fully round ends, so the control reads as a bubble rather than as a box. */
|
||||
val BubbleShape: Shape = RoundedCornerShape(percent = 50)
|
||||
|
||||
/**
|
||||
* The corner on a menu one of these opens.
|
||||
*
|
||||
* A radius rather than [BubbleShape]'s half-height: a menu is as tall as its options, and rounding
|
||||
* ends that tall would bow its sides. This is the roundest corner that still leaves a straight edge
|
||||
* beside a one-line option, which is the shortest menu here.
|
||||
*/
|
||||
val BubbleMenuShape: Shape = RoundedCornerShape(20.dp)
|
||||
Reference in new issue
Block a user