refactor(android): distill companion shell cleanup

This commit is contained in:
Ayaan Zaidi
2026-06-03 16:30:08 +05:30
parent 9159b3bf8e
commit 4f8740029a
3 changed files with 11 additions and 48 deletions

View File

@@ -793,10 +793,8 @@ private fun ChatShellScreen(
) {
ChatScreen(
viewModel = viewModel,
onBack = {},
onVoice = onVoice,
onOpenSessions = onOpenSessions,
showBackButton = false,
)
}
}

View File

@@ -38,7 +38,6 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material.icons.filled.Close
@@ -80,10 +79,8 @@ import java.util.Locale
@Composable
fun ChatScreen(
viewModel: MainViewModel,
onBack: () -> Unit,
onVoice: () -> Unit,
onOpenSessions: (() -> Unit)? = null,
showBackButton: Boolean = true,
onOpenSessions: () -> Unit,
) {
val messages by viewModel.chatMessages.collectAsState()
val historyLoading by viewModel.chatHistoryLoading.collectAsState()
@@ -162,12 +159,10 @@ fun ChatScreen(
thinkingLevel = thinkingLevel,
healthOk = healthOk,
pendingRunCount = pendingRunCount,
onBack = onBack,
onMore = {
viewModel.refreshChat()
viewModel.refreshChatSessions(limit = 100)
},
showBackButton = showBackButton,
)
ChatSessionSwitcher(
@@ -236,7 +231,7 @@ private fun ChatSessionSwitcher(
sessions: List<ChatSessionEntry>,
mainSessionKey: String,
onSelectSession: (String) -> Unit,
onOpenSessions: (() -> Unit)?,
onOpenSessions: () -> Unit,
) {
val choices =
remember(sessionKey, sessions, mainSessionKey) {
@@ -260,7 +255,7 @@ private fun ChatSessionSwitcher(
onClick = { onSelectSession(entry.key) },
)
}
if (onOpenSessions != null && sessions.size > choices.size) {
if (sessions.size > choices.size) {
Surface(
onClick = onOpenSessions,
modifier = Modifier.heightIn(min = 36.dp),
@@ -312,20 +307,14 @@ private fun ChatHeader(
thinkingLevel: String,
healthOk: Boolean,
pendingRunCount: Int,
onBack: () -> Unit,
onMore: () -> Unit,
showBackButton: Boolean,
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp),
) {
if (showBackButton) {
HeaderIcon(icon = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", onClick = onBack)
} else {
Box(modifier = Modifier.size(ClawTheme.spacing.touchTarget))
}
Box(modifier = Modifier.size(ClawTheme.spacing.touchTarget))
Column(
modifier = Modifier.weight(1f),

View File

@@ -4,22 +4,9 @@ import ai.openclaw.app.chat.ChatSessionEntry
private const val RECENT_WINDOW_MS = 24 * 60 * 60 * 1000L
/**
* Derive a human-friendly label from a raw session key.
* Examples:
* "telegram:g-agent-main-main" -> "Main"
* "agent:main:main" -> "Main"
* "discord:g-server-channel" -> "Server Channel"
* "my-custom-session" -> "My Custom Session"
*/
fun friendlySessionName(key: String): String {
// Strip common prefixes like "telegram:", "agent:", "discord:" etc.
val stripped = key.substringAfterLast(":")
// Remove leading "g-" prefix (gateway artifact)
val cleaned = if (stripped.startsWith("g-")) stripped.removePrefix("g-") else stripped
// Split on hyphens/underscores, title-case each word, collapse "main main" -> "Main"
val words =
cleaned
.split('-', '_')
@@ -79,7 +66,6 @@ fun resolveSessionChoices(
return result
}
/** Builds the compact top-of-chat session switcher without dropping main or the active session. */
fun resolveCompactSessionChoices(
currentSessionKey: String,
sessions: List<ChatSessionEntry>,
@@ -94,24 +80,14 @@ fun resolveCompactSessionChoices(
mainSessionKey = mainSessionKey,
nowMs = nowMs,
)
if (allChoices.size <= maxOptions) return allChoices
val mainKey = mainSessionKey.trim().ifEmpty { "main" }
val current = currentSessionKey.trim().let { if (it == "main" && mainKey != "main") mainKey else it }
val pinnedKeys = listOf(mainKey, current).filter { it.isNotBlank() }
val result = mutableListOf<ChatSessionEntry>()
val seen = mutableSetOf<String>()
val pinnedRank = listOf(mainKey, current).filter { it.isNotBlank() }.distinct().withIndex().associate { it.value to it.index }
val unpinnedRank = pinnedRank.size
pinnedKeys.forEach { key ->
allChoices.firstOrNull { it.key == key }?.let { entry ->
if (seen.add(entry.key)) result.add(entry)
}
}
allChoices.forEach { entry ->
if (result.size >= maxOptions) return@forEach
if (seen.add(entry.key)) result.add(entry)
}
return result
return allChoices
.withIndex()
.sortedWith(compareBy({ pinnedRank[it.value.key] ?: unpinnedRank }, { it.index }))
.take(maxOptions)
.map { it.value }
}