History

fix: remove duplicate toggle button and black lines around composer

seroxdesign committed 9 months ago

Commit 7e3ae931 parent 5bc16297 files · +96 −46Browse files

Unified · Split

7 files
  1. frontend/src/app/chat/_components/input/tool-belt.tsx +1 −1
  2. frontend/src/app/chat/_components/layout/chat-toolbelt-dock.tsx +1 −1
  3. frontend/src/app/chat/_components/layout/unified-sidebar.tsx +0 −11
  4. swift-client/sources/features/chat/chat-detail-view.swift +8 −2
  5. swift-client/sources/features/chat/chat-message-row.swift +8 −4
  6. swift-client/sources/features/chat/chat-streaming-message-view.swift +59 −18
  7. swift-client/sources/features/chat/chat-usage-bar.swift +19 −9
frontend/src/app/chat/_components/input/tool-belt.tsx+1−1
@@ -263,7 +263,7 @@ export function ToolBelt({ · 262 unmodified lines
263263 const canSend = value.trim() || attachments.length > 0;
264264
265265 return (
266− <div className="px-2 md:px-3 pb-0 bg-(--background)">
266+ <div className="px-2 md:px-3 pb-0">
267267 <div className="w-full max-w-none md:max-w-4xl md:mx-auto px-0 md:px-0">
268268 <AttachmentsPreview
269269 attachments={attachments}
frontend/src/app/chat/_components/layout/chat-toolbelt-dock.tsx+1−1
@@ -11,7 +11,7 @@ export function ChatToolbeltDock({ toolBelt, showEmptyState }: ChatToolbeltDockP · 10 unmodified lines
1111 return (
1212 <div className="fixed left-0 right-0 bottom-0 z-20 md:static">
1313 {/* Mobile: flush to bottom, no extra padding */}
14− <div className="md:hidden bg-[hsl(30,5%,10.5%)]">
14+ <div className="md:hidden">
1515 {toolBelt}
1616 </div>
1717 {!showEmptyState && (
frontend/src/app/chat/_components/layout/unified-sidebar.tsx+0−11
@@ -117,17 +117,6 @@ export function UnifiedSidebar({ · 116 unmodified lines
117117 {children}
118118 </div>
119119
120− {/* Toggle button when closed */}
121− {!isOpen && (
122− <button
123− onClick={onToggle}
124− className="hidden md:flex items-center justify-center w-8 h-8 mt-4 mr-2 rounded-lg bg-white/[0.03] hover:bg-white/[0.06] border border-white/[0.06] text-[#666] hover:text-[#888] transition-colors flex-shrink-0"
125− title="Open sidebar"
126− >
127− <PanelRightOpen className="h-4 w-4" />
128− </button>
129− )}
130−
131120 {/* Resizable sidebar */}
132121 {isOpen && (
133122 <div
swift-client/sources/features/chat/chat-detail-view.swift+8−2
@@ -16,11 +16,17 @@ struct ChatDetailView: View { · 15 unmodified lines
1616 ScrollView {
1717 VStack(spacing: 12) {
1818 if let modelId = model.sessionModel {
19− HStack {
20− Text(modelId).font(AppTheme.captionFont).foregroundColor(AppTheme.muted)
19+ HStack(spacing: 6) {
20+ Image(systemName: "cpu")
21+ .font(.system(size: 10))
22+ .foregroundColor(AppTheme.accentStrong)
23+ Text(modelId)
24+ .font(AppTheme.captionFont.weight(.medium))
25+ .foregroundColor(AppTheme.muted)
2126 Spacer()
2227 }
2328 .padding(.horizontal, 4)
29+ .padding(.bottom, 4)
2430 }
2531 if let error = model.error {
2632 HStack {
swift-client/sources/features/chat/chat-message-row.swift+8−4
@@ -27,10 +27,14 @@ struct ChatMessageRow: View { · 26 unmodified lines
2727 Text(message.content ?? "")
2828 .font(AppTheme.bodyFont)
2929 .foregroundColor(AppTheme.foreground)
30− .padding(.horizontal, 14)
31− .padding(.vertical, 10)
32− .background(AppTheme.card)
33− .cornerRadius(16)
30+ .padding(.horizontal, 16)
31+ .padding(.vertical, 12)
32+ .background(AppTheme.accent.opacity(0.25))
33+ .cornerRadius(18)
34+ .overlay(
35+ RoundedRectangle(cornerRadius: 18)
36+ .stroke(AppTheme.accent.opacity(0.4), lineWidth: 1)
37+ )
3438 }
3539 }
3640
swift-client/sources/features/chat/chat-streaming-message-view.swift+59−18
@@ -1,3 +1,4 @@
1+// CRITICAL
12 import SwiftUI
23
34 struct ChatStreamingMessageView: View {
@@ -6,27 +7,67 @@ struct ChatStreamingMessageView: View { · 2 unmodified lines
67 let onShowActions: (AgentMeta) -> Void
78
89 var body: some View {
9− let message = StoredMessage(
10− id: "streaming",
11− role: "assistant",
12− content: service.streamingContent,
13− model: nil,
14− toolCalls: nil
15− )
16− let meta = AgentMeta(
17− thinkingBlocks: service.streamingReasoning.isEmpty ? [] : [service.streamingReasoning],
18− toolCalls: service.streamingToolCalls,
19− toolResults: []
20− )
21− ChatMessageRow(
22− message: message,
23− isStreaming: true,
24− meta: meta,
25− onShowActions: { onShowActions($0) }
26− )
10+ VStack(alignment: .leading, spacing: 10) {
11+ // Streaming content
12+ if !service.streamingContent.isEmpty {
13+ MarkdownText(content: service.streamingContent)
14+ .foregroundColor(AppTheme.foreground)
15+ }
16+
17+ // Live thinking/tracing indicator
18+ if !service.streamingReasoning.isEmpty || !service.streamingToolCalls.isEmpty {
19+ StreamingMetaIndicator(
20+ reasoning: service.streamingReasoning,
21+ toolCalls: service.streamingToolCalls
22+ )
23+ }
24+ }
25+ .frame(maxWidth: .infinity, alignment: .leading)
2726 .id("streaming")
2827 .onChange(of: service.streamingContent) { _, _ in
2928 scrollProxy.scrollTo("streaming", anchor: .bottom)
3029 }
30+ .onChange(of: service.streamingReasoning) { _, _ in
31+ scrollProxy.scrollTo("streaming", anchor: .bottom)
32+ }
33+ }
34+}
35+
36+private struct StreamingMetaIndicator: View {
37+ let reasoning: String
38+ let toolCalls: [ToolCall]
39+
40+ var body: some View {
41+ VStack(alignment: .leading, spacing: 8) {
42+ if !reasoning.isEmpty {
43+ HStack(spacing: 6) {
44+ Image(systemName: "brain")
45+ .font(.system(size: 10))
46+ .foregroundColor(AppTheme.accentStrong)
47+ Text("Reasoning...")
48+ .font(AppTheme.captionFont)
49+ .foregroundColor(AppTheme.accentStrong)
50+ }
51+ .padding(.horizontal, 10)
52+ .padding(.vertical, 5)
53+ .background(AppTheme.accent.opacity(0.15))
54+ .cornerRadius(8)
55+ }
56+
57+ if !toolCalls.isEmpty {
58+ HStack(spacing: 6) {
59+ Image(systemName: "wrench.and.screwdriver")
60+ .font(.system(size: 10))
61+ .foregroundColor(AppTheme.warning)
62+ Text("Using \(toolCalls.count) tool\(toolCalls.count == 1 ? "" : "s")...")
63+ .font(AppTheme.captionFont)
64+ .foregroundColor(AppTheme.warning)
65+ }
66+ .padding(.horizontal, 10)
67+ .padding(.vertical, 5)
68+ .background(AppTheme.warning.opacity(0.15))
69+ .cornerRadius(8)
70+ }
71+ }
3172 }
3273 }
swift-client/sources/features/chat/chat-usage-bar.swift+19−9
@@ -1,3 +1,4 @@
1+// CRITICAL
12 import SwiftUI
23
34 struct ChatUsageBar: View {
@@ -5,12 +6,12 @@ struct ChatUsageBar: View { · 1 unmodified line
56
67 var body: some View {
78 if let usage {
8− HStack(spacing: 12) {
9− UsagePill(label: "Prompt", value: usage.promptTokens)
10− UsagePill(label: "Completion", value: usage.completionTokens)
11− UsagePill(label: "Total", value: usage.totalTokens)
9+ HStack(spacing: 8) {
10+ UsagePill(label: "Input", value: usage.promptTokens, color: AppTheme.accentStrong)
11+ UsagePill(label: "Output", value: usage.completionTokens, color: AppTheme.success)
12+ UsagePill(label: "Total", value: usage.totalTokens, color: AppTheme.foreground)
1213 }
13− .padding(.horizontal, 16)
14+ .padding(.horizontal, 4)
1415 }
1516 }
1617 }
@@ -18,15 +19,24 @@ struct ChatUsageBar: View { · 1 unmodified line
1819 struct UsagePill: View {
1920 let label: String
2021 let value: Int
22+ let color: Color
2123
2224 var body: some View {
23− VStack(spacing: 2) {
24− Text(label).font(AppTheme.captionFont).foregroundColor(AppTheme.muted)
25− Text("\(value)").font(AppTheme.monoFont)
25+ HStack(spacing: 4) {
26+ Text(label)
27+ .font(AppTheme.captionFont)
28+ .foregroundColor(AppTheme.muted)
29+ Text("\(value)")
30+ .font(AppTheme.monoFont.weight(.medium))
31+ .foregroundColor(color)
2632 }
2733 .padding(.vertical, 6)
2834 .padding(.horizontal, 10)
2935 .background(AppTheme.card)
30− .cornerRadius(10)
36+ .cornerRadius(8)
37+ .overlay(
38+ RoundedRectangle(cornerRadius: 8)
39+ .stroke(AppTheme.border, lineWidth: 1)
40+ )
3141 }
3242 }