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
@@ -15,20 +15,11 @@ import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import java.time.OffsetDateTime
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Window bars for the account's rate limits, with reset times.
|
||||
@@ -41,23 +32,7 @@ import kotlinx.coroutines.withContext
|
||||
* handles that itself.
|
||||
*/
|
||||
@Composable
|
||||
fun UsageDialog(settings: ServerSettings, onDismiss: () -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
var state by remember { mutableStateOf<LoadState<List<UsageSnapshot>>>(LoadState.Loading) }
|
||||
|
||||
fun refresh() {
|
||||
state = LoadState.Loading
|
||||
scope.launch {
|
||||
state =
|
||||
try {
|
||||
withContext(Dispatchers.IO) { LoadState.Loaded(fetchUsage(settings)) }
|
||||
} catch (e: ApiException) {
|
||||
LoadState.failed(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
|
||||
fun UsageDialog(feed: UsageFeed, onDismiss: () -> Unit) {
|
||||
// A plain Dialog rather than an AlertDialog, for the spacing alone. AlertDialog fixes the
|
||||
// gaps between its title, its content and its buttons at sizes meant for a sentence of prose
|
||||
// and a decision; this is a dense read-out, and those gaps left a band of empty dialog above
|
||||
@@ -84,7 +59,14 @@ fun UsageDialog(settings: ServerSettings, onDismiss: () -> Unit) {
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
GlyphButton(REFRESH_GLYPH, "Refresh usage", { refresh() })
|
||||
// A spinner in the button's place while the answer is on its way, since the
|
||||
// numbers under it stay put during a refresh -- without it, pressing refresh
|
||||
// over an unchanged read-out looks like a button that does nothing.
|
||||
if (feed.refreshing) {
|
||||
GlyphSpinner("Refreshing usage")
|
||||
} else {
|
||||
GlyphButton(REFRESH_GLYPH, "Refresh usage", feed.refresh)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
// Scrolls rather than being trimmed: a machine can report any number of windows
|
||||
@@ -92,7 +74,7 @@ fun UsageDialog(settings: ServerSettings, onDismiss: () -> Unit) {
|
||||
// running out of room is silent. `fill = false` so a short read-out keeps a short
|
||||
// dialog instead of stretching to the window.
|
||||
Column(Modifier.weight(1f, fill = false).verticalScroll(rememberScrollState())) {
|
||||
UsageBody(state)
|
||||
UsageBody(feed.snapshots)
|
||||
}
|
||||
TextButton(onClick = onDismiss, modifier = Modifier.align(Alignment.End)) {
|
||||
Text("Close")
|
||||
|
||||
Reference in new issue
Block a user