mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 11:28:38 +00:00
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:
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user