Merge branch 'main' of git.arirex.me:iris/ai-app
This commit is contained in:
commit
3ecc550c1e
3 files changed
+86
-7
No files matched your search
@@ -59,6 +59,7 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -764,6 +765,21 @@ fun SessionScreen(
|
||||
// stays started.
|
||||
DisposableEffect(summary.id) { onDispose { activeStream.get()?.close() } }
|
||||
|
||||
// Nothing gets announced about the session somebody is reading; see NotificationService.
|
||||
// RESUMED rather than STARTED because "looking at it" means the foreground -- a session left
|
||||
// on this screen behind another app is one whose notifications are still wanted, and STARTED
|
||||
// covers that case too.
|
||||
LaunchedEffect(summary.id, lifecycleOwner) {
|
||||
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||
NotificationService.showing(context, summary.id)
|
||||
try {
|
||||
awaitCancellation()
|
||||
} finally {
|
||||
NotificationService.stoppedShowing(summary.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Back at the newest end, so the backlog [apply] held can land. Everything at once rather
|
||||
// than paced out: they are at the bottom, which is the one place the list is allowed to
|
||||
// follow new content, and drip-feeding it would only make that following last longer.
|
||||
@@ -1314,7 +1330,11 @@ fun SessionScreen(
|
||||
if (offeredModels.isNotEmpty()) {
|
||||
PickerButton(
|
||||
current = modelLabel(model),
|
||||
options = offeredModels,
|
||||
// What the machine offers, plus the state a session is in when it
|
||||
// has chosen none of them. The button has always been able to say
|
||||
// "default"; until this the list could not, so leaving it was a
|
||||
// one-way trip.
|
||||
options = listOf(DEFAULT_MODEL) + offeredModels,
|
||||
// Not set here. The button follows what the session reports it
|
||||
// is set to, which arrives a moment later and is sometimes a
|
||||
// different answer -- a name the CLI resolved, or no change at all
|
||||
@@ -1322,7 +1342,7 @@ fun SessionScreen(
|
||||
// Asked about first, unless there is nothing to lose by it --
|
||||
// see [ModelSwitchWarning].
|
||||
onPick = { chosen ->
|
||||
if (chosen == model || items.isEmpty()) {
|
||||
if (modelLabel(chosen) == modelLabel(model) || items.isEmpty()) {
|
||||
act { setSessionModel(settings, summary.id, chosen) }
|
||||
} else {
|
||||
pendingModel = chosen
|
||||
@@ -1632,13 +1652,29 @@ private fun PickerButton(current: String, options: List<String>, onPick: (String
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
// Not focusable, so opening it does not take focus from the message
|
||||
// field and dismiss the keyboard. Changing the model mid-sentence
|
||||
// is an aside, not a departure from what you were typing.
|
||||
// Two departures from the defaults, both deliberate.
|
||||
//
|
||||
// Not focusable, so opening it does not take focus from the message field and dismiss the
|
||||
// keyboard. Changing the model mid-sentence is an aside, not a departure from what you
|
||||
// were typing.
|
||||
//
|
||||
// Not clipped, which is what puts the menu on the button instead of floating above it.
|
||||
// Compose measures the anchor in *window* coordinates -- this app draws edge to edge, so
|
||||
// that window is the whole screen -- but asks whether the menu fits inside the *visible*
|
||||
// frame, which is the screen less the status and navigation bars. Two spaces, one
|
||||
// comparison: sitting just above a button near the bottom then looks like an overflow,
|
||||
// and the menu falls back to a fixed 48dp above the bottom of the visible frame. Measured
|
||||
// on the emulator, that left the menu's foot 142px -- the status bar's height, exactly --
|
||||
// clear of the button that opened it. Turning clipping off makes both questions about the
|
||||
// same window. What it gives up is that the keyboard stops counting as an edge: with the
|
||||
// IME up the menu opens downwards over it rather than upwards over the transcript. That
|
||||
// is the lesser fault -- it is still attached to the button that opened it, which is the
|
||||
// whole complaint -- and correcting it would mean supplying a position provider, which
|
||||
// this menu takes no parameter for.
|
||||
DropdownMenu(
|
||||
expanded = open,
|
||||
onDismissRequest = { open = false },
|
||||
properties = PopupProperties(focusable = false),
|
||||
properties = PopupProperties(focusable = false, clippingEnabled = false),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
DropdownMenuItem(
|
||||
|
||||
Reference in new issue
Block a user