feat(android): soften chat role labels and deduplicate session header

Rename role labels to You/OpenClaw/System, update streaming label to
OpenClaw · Live, and remove the redundant SESSION row + Connected pill
since the top bar and chip row already convey both.
This commit is contained in:
Ayaan Zaidi
2026-03-13 14:25:55 +05:30
parent c761b5b8a8
commit 8b0e16a1c8
2 changed files with 23 additions and 71 deletions

View File

@@ -151,7 +151,7 @@ fun ChatPendingToolsBubble(toolCalls: List<ChatPendingToolCall>) {
ChatBubbleContainer( ChatBubbleContainer(
style = bubbleStyle("assistant"), style = bubbleStyle("assistant"),
roleLabel = "TOOLS", roleLabel = "Tools",
) { ) {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text("Running tools...", style = mobileCaption1.copy(fontWeight = FontWeight.SemiBold), color = mobileTextSecondary) Text("Running tools...", style = mobileCaption1.copy(fontWeight = FontWeight.SemiBold), color = mobileTextSecondary)
@@ -188,7 +188,7 @@ fun ChatPendingToolsBubble(toolCalls: List<ChatPendingToolCall>) {
fun ChatStreamingAssistantBubble(text: String) { fun ChatStreamingAssistantBubble(text: String) {
ChatBubbleContainer( ChatBubbleContainer(
style = bubbleStyle("assistant").copy(borderColor = mobileAccent), style = bubbleStyle("assistant").copy(borderColor = mobileAccent),
roleLabel = "ASSISTANT · LIVE", roleLabel = "OpenClaw · Live",
) { ) {
ChatMarkdown(text = text, textColor = mobileText) ChatMarkdown(text = text, textColor = mobileText)
} }
@@ -224,9 +224,9 @@ private fun bubbleStyle(role: String): ChatBubbleStyle {
private fun roleLabel(role: String): String { private fun roleLabel(role: String): String {
return when (role) { return when (role) {
"user" -> "USER" "user" -> "You"
"system" -> "SYSTEM" "system" -> "System"
else -> "ASSISTANT" else -> "OpenClaw"
} }
} }

View File

@@ -42,12 +42,8 @@ import ai.openclaw.app.ui.mobileCallout
import ai.openclaw.app.ui.mobileCaption1 import ai.openclaw.app.ui.mobileCaption1
import ai.openclaw.app.ui.mobileCaption2 import ai.openclaw.app.ui.mobileCaption2
import ai.openclaw.app.ui.mobileDanger import ai.openclaw.app.ui.mobileDanger
import ai.openclaw.app.ui.mobileSuccess
import ai.openclaw.app.ui.mobileSuccessSoft
import ai.openclaw.app.ui.mobileText import ai.openclaw.app.ui.mobileText
import ai.openclaw.app.ui.mobileTextSecondary import ai.openclaw.app.ui.mobileTextSecondary
import ai.openclaw.app.ui.mobileWarning
import ai.openclaw.app.ui.mobileWarningSoft
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -106,7 +102,6 @@ fun ChatSheetContent(viewModel: MainViewModel) {
sessionKey = sessionKey, sessionKey = sessionKey,
sessions = sessions, sessions = sessions,
mainSessionKey = mainSessionKey, mainSessionKey = mainSessionKey,
healthOk = healthOk,
onSelectSession = { key -> viewModel.switchChatSession(key) }, onSelectSession = { key -> viewModel.switchChatSession(key) },
) )
@@ -160,77 +155,34 @@ private fun ChatThreadSelector(
sessionKey: String, sessionKey: String,
sessions: List<ChatSessionEntry>, sessions: List<ChatSessionEntry>,
mainSessionKey: String, mainSessionKey: String,
healthOk: Boolean,
onSelectSession: (String) -> Unit, onSelectSession: (String) -> Unit,
) { ) {
val sessionOptions = resolveSessionChoices(sessionKey, sessions, mainSessionKey = mainSessionKey) val sessionOptions = resolveSessionChoices(sessionKey, sessions, mainSessionKey = mainSessionKey)
val currentSessionLabel =
friendlySessionName(sessionOptions.firstOrNull { it.key == sessionKey }?.displayName ?: sessionKey)
Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp)) { Row(
Row( modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()),
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.SpaceBetween, ) {
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically, for (entry in sessionOptions) {
) { val active = entry.key == sessionKey
Text( Surface(
text = "SESSION", onClick = { onSelectSession(entry.key) },
style = mobileCaption1.copy(fontWeight = FontWeight.Bold, letterSpacing = 0.8.sp), shape = RoundedCornerShape(14.dp),
color = mobileTextSecondary, color = if (active) mobileAccent else Color.White,
) border = BorderStroke(1.dp, if (active) Color(0xFF154CAD) else mobileBorderStrong),
Row(horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) { tonalElevation = 0.dp,
shadowElevation = 0.dp,
) {
Text( Text(
text = currentSessionLabel, text = friendlySessionName(entry.displayName ?: entry.key),
style = mobileCallout.copy(fontWeight = FontWeight.SemiBold), style = mobileCaption1.copy(fontWeight = if (active) FontWeight.Bold else FontWeight.SemiBold),
color = mobileText, color = if (active) Color.White else mobileText,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
) )
ChatConnectionPill(healthOk = healthOk)
} }
} }
Row(
modifier = Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
for (entry in sessionOptions) {
val active = entry.key == sessionKey
Surface(
onClick = { onSelectSession(entry.key) },
shape = RoundedCornerShape(14.dp),
color = if (active) mobileAccent else Color.White,
border = BorderStroke(1.dp, if (active) Color(0xFF154CAD) else mobileBorderStrong),
tonalElevation = 0.dp,
shadowElevation = 0.dp,
) {
Text(
text = friendlySessionName(entry.displayName ?: entry.key),
style = mobileCaption1.copy(fontWeight = if (active) FontWeight.Bold else FontWeight.SemiBold),
color = if (active) Color.White else mobileText,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
)
}
}
}
}
}
@Composable
private fun ChatConnectionPill(healthOk: Boolean) {
Surface(
shape = RoundedCornerShape(999.dp),
color = if (healthOk) mobileSuccessSoft else mobileWarningSoft,
border = BorderStroke(1.dp, if (healthOk) mobileSuccess.copy(alpha = 0.35f) else mobileWarning.copy(alpha = 0.35f)),
) {
Text(
text = if (healthOk) "Connected" else "Offline",
style = mobileCaption1.copy(fontWeight = FontWeight.SemiBold),
color = if (healthOk) mobileSuccess else mobileWarning,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp),
)
} }
} }