




























@@ -38,6 +38,7 @@ import androidx.compose.material.icons.filled.Mic
3838import androidx.compose.material.icons.filled.MoreVert
3939import androidx.compose.material.icons.filled.Refresh
4040import androidx.compose.material.icons.filled.StarBorder
41+import androidx.compose.material3.HorizontalDivider
4142import androidx.compose.material3.Icon
4243import androidx.compose.material3.Surface
4344import androidx.compose.material3.Text
@@ -141,6 +142,7 @@ fun V2ChatScreen(
141142 pendingToolCalls = pendingToolCalls,
142143 streamingAssistantText = streamingAssistantText,
143144 healthOk = healthOk,
145+ onStarterPrompt = { prompt -> input = prompt },
144146 modifier = Modifier.weight(1f),
145147 )
146148@@ -268,6 +270,7 @@ private fun V2ChatMessageList(
268270pendingToolCalls: List<ChatPendingToolCall>,
269271streamingAssistantText: String?,
270272healthOk: Boolean,
273+onStarterPrompt: (String) -> Unit,
271274modifier: Modifier = Modifier,
272275) {
273276val listState = rememberLazyListState()
@@ -315,32 +318,98 @@ private fun V2ChatMessageList(
315318 }
316319317320if (messages.isEmpty() && pendingRunCount == 0 && pendingToolCalls.isEmpty() && stream.isNullOrBlank()) {
318-V2EmptyChatHint(healthOk = healthOk, modifier = Modifier.align(Alignment.Center))
321+V2EmptyChatHint(healthOk = healthOk, onStarterPrompt = onStarterPrompt, modifier = Modifier.align(Alignment.Center))
319322 }
320323 }
321324}
322325323326@Composable
324327private fun V2EmptyChatHint(
325328healthOk: Boolean,
329+onStarterPrompt: (String) -> Unit,
326330modifier: Modifier = Modifier,
327331) {
328-Column(modifier = modifier.padding(horizontal = 32.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(7.dp)) {
329-Text(text = "No messages yet", style = ClawTheme.type.title.copy(fontSize = 14.sp, lineHeight = 18.sp), color = ClawTheme.colors.text)
330-Text(
331- text =
332-if (healthOk) {
333-"Ask OpenClaw anything."
334- } else {
335-"Reconnect your Gateway from Settings."
336- },
337- style = ClawTheme.type.body,
338- color = ClawTheme.colors.textMuted,
339- textAlign = TextAlign.Center,
340- )
332+Column(
333+ modifier = modifier.fillMaxWidth().padding(horizontal = 2.dp),
334+ horizontalAlignment = Alignment.CenterHorizontally,
335+ verticalArrangement = Arrangement.spacedBy(12.dp),
336+ ) {
337+Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(5.dp)) {
338+Text(text = if (healthOk) "Ready when you are" else "Gateway offline", style = ClawTheme.type.title.copy(fontSize = 18.sp, lineHeight = 23.sp), color = ClawTheme.colors.text)
339+Text(
340+ text =
341+if (healthOk) {
342+"Start with a prompt, or use voice."
343+ } else {
344+"Reconnect from Settings to send messages."
345+ },
346+ style = ClawTheme.type.body,
347+ color = ClawTheme.colors.textMuted,
348+ textAlign = TextAlign.Center,
349+ )
350+ }
351+if (healthOk) {
352+V2StarterPromptList(onStarterPrompt = onStarterPrompt)
353+ }
341354 }
342355}
343356357+@Composable
358+private fun V2StarterPromptList(onStarterPrompt: (String) -> Unit) {
359+ClawPanel(contentPadding = PaddingValues(horizontal = 0.dp, vertical = 0.dp)) {
360+Column {
361+ starterPrompts.forEachIndexed { index, prompt ->
362+V2StarterPromptRow(prompt = prompt, onClick = { onStarterPrompt(prompt.message) })
363+if (index != starterPrompts.lastIndex) {
364+HorizontalDivider(color = ClawTheme.colors.border, thickness = 1.dp)
365+ }
366+ }
367+ }
368+ }
369+}
370+371+@Composable
372+private fun V2StarterPromptRow(
373+prompt: V2StarterPrompt,
374+onClick: () -> Unit,
375+) {
376+Surface(onClick = onClick, color = Color.Transparent, contentColor = ClawTheme.colors.text) {
377+Row(
378+ modifier = Modifier.fillMaxWidth().heightIn(min = 54.dp).padding(horizontal = 10.dp, vertical = 6.dp),
379+ verticalAlignment = Alignment.CenterVertically,
380+ horizontalArrangement = Arrangement.spacedBy(10.dp),
381+ ) {
382+Box(
383+ modifier =
384+Modifier
385+ .size(30.dp)
386+ .background(ClawTheme.colors.surfacePressed, RoundedCornerShape(ClawTheme.radii.row)),
387+ contentAlignment = Alignment.Center,
388+ ) {
389+Text(text = prompt.mark, style = ClawTheme.type.label, color = ClawTheme.colors.text)
390+ }
391+Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(1.dp)) {
392+Text(text = prompt.title, style = ClawTheme.type.body, color = ClawTheme.colors.text, maxLines = 1)
393+Text(text = prompt.subtitle, style = ClawTheme.type.caption, color = ClawTheme.colors.textMuted, maxLines = 1, overflow = TextOverflow.Ellipsis)
394+ }
395+ }
396+ }
397+}
398+399+private data class V2StarterPrompt(
400+val mark: String,
401+val title: String,
402+val subtitle: String,
403+val message: String,
404+)
405+406+private val starterPrompts =
407+listOf(
408+V2StarterPrompt(mark = "1", title = "Catch me up", subtitle = "Summarize recent sessions and next steps.", message = "Catch me up on my recent OpenClaw sessions and suggest next steps."),
409+V2StarterPrompt(mark = "2", title = "Plan the work", subtitle = "Turn a goal into an actionable checklist.", message = "Help me turn this goal into a practical checklist: "),
410+V2StarterPrompt(mark = "3", title = "Use this phone", subtitle = "Ask OpenClaw to use Android capabilities.", message = "What can you help me do from this phone right now?"),
411+ )
412+344413@Composable
345414private fun V2ChatBubble(
346415role: String,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。