-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathUserMessage.swift
More file actions
107 lines (95 loc) · 3.3 KB
/
UserMessage.swift
File metadata and controls
107 lines (95 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import ComposableArchitecture
import ChatService
import Foundation
import MarkdownUI
import SharedUIComponents
import SwiftUI
import Status
import Cache
import ChatTab
import ConversationServiceProvider
import SwiftUIFlowLayout
private let MAX_TEXT_LENGTH = 10000 // Maximum characters to prevent crashes
struct UserMessage: View {
var r: Double { messageBubbleCornerRadius }
let id: String
let text: String
let imageReferences: [ImageReference]
let chat: StoreOf<Chat>
@Environment(\.colorScheme) var colorScheme
@ObservedObject private var statusObserver = StatusObserver.shared
struct AvatarView: View {
@ObservedObject private var avatarViewModel = AvatarViewModel.shared
var body: some View {
if let avatarImage = avatarViewModel.avatarImage {
avatarImage
.resizable()
.aspectRatio(contentMode: .fill)
.scaledFrame(width: 24, height: 24)
.clipShape(Circle())
} else {
Image(systemName: "person.circle")
.resizable()
.scaledToFit()
.scaledFrame(width: 24, height: 24)
}
}
}
// Truncate the displayed user message if it's too long.
private var displayText: String {
if text.count > MAX_TEXT_LENGTH {
return String(text.prefix(MAX_TEXT_LENGTH)) + "\n… (message too long, rest hidden)"
}
return text
}
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 4) {
AvatarView()
Text(statusObserver.authStatus.username ?? "")
.scaledFont(size: 13, weight: .semibold)
.padding(2)
Spacer()
}
ThemedMarkdownText(text: displayText, chat: chat)
.frame(maxWidth: .infinity, alignment: .leading)
if !imageReferences.isEmpty {
FlowLayout(mode: .scrollable, items: imageReferences, itemSpacing: 4) { item in
ImageReferenceItemView(item: item)
}
}
}
}
.shadow(color: .black.opacity(0.05), radius: 6)
}
}
struct UserMessage_Previews: PreviewProvider {
static var previews: some View {
let chatTabInfo = ChatTabInfo(id: "id", workspacePath: "path", username: "name")
UserMessage(
id: "A",
text: #"""
Please buy me a coffee!
| Coffee | Milk |
|--------|------|
| Espresso | No |
| Latte | Yes |
```swift
func foo() {}
```
```objectivec
- (void)bar {}
```
"""#,
imageReferences: [],
chat: .init(
initialState: .init(history: [] as [DisplayedChatMessage], isReceivingMessage: false),
reducer: { Chat(service: ChatService.service(for: chatTabInfo)) }
)
)
.padding()
.fixedSize(horizontal: true, vertical: true)
.background(Color.yellow)
}
}