From b417fe57279f6b44be11fc35e7d7a0c288c9037a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 3 Jan 2026 05:07:13 +0100 Subject: [PATCH] fix: show rich session names in chat UIs --- CHANGELOG.md | 1 + .../com/steipete/clawdis/node/ui/chat/ChatComposer.kt | 6 +++--- .../ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift | 8 +++++++- ui/src/ui/views/chat.ts | 6 +++++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d616c28..e88e39d71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ - Gog calendar: format date ranges as RFC 3339 with timezone to satisfy Google Calendar API (thanks @jayhickey). - macOS onboarding: add scrollable page gutter for overflowing content (#105) — thanks @thewilloftheshadow. - Chat UI: keep the chat scrolled to the latest message after switching sessions. +- Chat UI: show rich session display names in Web Chat + SwiftUI + Android. - Auto-reply: stream completed reply blocks as soon as they finish (configurable default + break); skip empty tool-only blocks unless verbose. - Discord: avoid duplicate sends when block streaming is enabled (race with typing hook). - Providers: make outbound text chunk limits configurable via `*.textChunkLimit` (defaults remain 4000/Discord 2000). diff --git a/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/chat/ChatComposer.kt b/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/chat/ChatComposer.kt index 8ac6f0aca..3bba710cf 100644 --- a/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/chat/ChatComposer.kt +++ b/apps/android/app/src/main/java/com/steipete/clawdis/node/ui/chat/ChatComposer.kt @@ -148,7 +148,7 @@ fun ChatComposer( ) Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - ConnectionPill(sessionKey = sessionKey, healthOk = healthOk) + ConnectionPill(sessionLabel = currentSessionLabel, healthOk = healthOk) Spacer(modifier = Modifier.weight(1f)) if (pendingRunCount > 0) { @@ -186,7 +186,7 @@ fun ChatComposer( } @Composable -private fun ConnectionPill(sessionKey: String, healthOk: Boolean) { +private fun ConnectionPill(sessionLabel: String, healthOk: Boolean) { Surface( shape = RoundedCornerShape(999.dp), color = MaterialTheme.colorScheme.surfaceContainerHighest, @@ -201,7 +201,7 @@ private fun ConnectionPill(sessionKey: String, healthOk: Boolean) { shape = androidx.compose.foundation.shape.CircleShape, color = if (healthOk) Color(0xFF2ECC71) else Color(0xFFF39C12), ) {} - Text(sessionKey, style = MaterialTheme.typography.labelSmall) + Text(sessionLabel, style = MaterialTheme.typography.labelSmall) Text( if (healthOk) "Connected" else "Connecting…", style = MaterialTheme.typography.labelSmall, diff --git a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift index d34c03a53..f7f919439 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift @@ -209,7 +209,7 @@ struct ClawdisChatComposer: View { Circle() .fill(self.viewModel.healthOK ? .green : .orange) .frame(width: 7, height: 7) - Text(self.viewModel.sessionKey) + Text(self.activeSessionLabel) .font(.caption2.weight(.semibold)) Text(self.viewModel.healthOK ? "Connected" : "Connecting…") .font(.caption2) @@ -221,6 +221,12 @@ struct ClawdisChatComposer: View { .clipShape(Capsule()) } + private var activeSessionLabel: String { + let match = self.viewModel.sessions.first { $0.key == self.viewModel.sessionKey } + let trimmed = match?.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + return trimmed.isEmpty ? self.viewModel.sessionKey : trimmed + } + private var editorOverlay: some View { ZStack(alignment: .topLeading) { if self.viewModel.input.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { diff --git a/ui/src/ui/views/chat.ts b/ui/src/ui/views/chat.ts index 7fca2f9bd..70812b683 100644 --- a/ui/src/ui/views/chat.ts +++ b/ui/src/ui/views/chat.ts @@ -43,7 +43,10 @@ export function renderChat(props: ChatProps) { props.onSessionKeyChange((e.target as HTMLSelectElement).value)} > ${sessionOptions.map( - (entry) => html``, + (entry) => + html``, )} @@ -115,6 +118,7 @@ export function renderChat(props: ChatProps) { type SessionOption = { key: string; updatedAt?: number | null; + displayName?: string; }; function resolveSessionOptions(