Merge branch 'main' of git.arirex.me:iris/ai-app

This commit is contained in:
iris committed 2026-08-30 14:27:31 -04:00
commit d981d63bcc
5 files changed
+549 -69

No files matched your search

@@ -568,6 +568,12 @@ fun SessionScreen(
var compactingFor by remember { mutableStateOf<Long?>(null) }
var streamError by remember { mutableStateOf<String?>(null) }
var actionError by remember { mutableStateOf<String?>(null) }
// Whether the composer's process button has a request out. What it does next is decided from
// the session's status, and the status only changes once the server has answered and the
// stream has carried it back -- so two presses in that gap are two requests, both decided
// against the state before either of them. The server refuses the second one, but a control
// that can be pressed while its own last press is still in flight is asking to be.
var processInFlight by remember { mutableStateOf(false) }
val context = LocalContext.current
// Seeded from what was left in the box last time and written back on every keystroke, so
// leaving the screen -- or the system reclaiming the app -- does not throw away a half-typed
@@ -1030,7 +1036,7 @@ fun SessionScreen(
}
}
fun act(onFailure: () -> Unit = {}, action: () -> Unit) {
fun act(onFailure: () -> Unit = {}, onDone: () -> Unit = {}, action: () -> Unit) {
scope.launch {
try {
withContext(Dispatchers.IO) { action() }
@@ -1038,6 +1044,11 @@ fun SessionScreen(
} catch (e: ApiException) {
actionError = e.message
onFailure()
} finally {
// Whatever happened, including the failure above: a caller that re-enables a
// control here must get it back on the path where the request was refused too,
// or the refusal is what disables the control permanently.
onDone()
}
}
}
@@ -1538,7 +1549,13 @@ fun SessionScreen(
else -> ProcessAction.Stop
}
Button(
onClick = { act { process.perform(settings, summary.id) } },
onClick = {
processInFlight = true
act(onDone = { processInFlight = false }) {
process.perform(settings, summary.id)
}
},
enabled = !processInFlight,
colors = actionButtonColors(process.colour()),
) {
Glyph(