Skip to content

Commit 6e58d30

Browse files
authored
Add basic markdown support for assist chat messages (#3689)
1 parent 22d8b14 commit 6e58d30

File tree

4 files changed

+103
-8
lines changed

4 files changed

+103
-8
lines changed

Sources/App/Assist/AssistView.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,15 @@ struct AssistView: View {
112112
AssistTypingIndicator()
113113
.padding(.vertical, Spaces.half)
114114
} else {
115-
Text(item.content)
115+
Text(item.markdown)
116116
}
117117
}
118118
.padding(8)
119119
.padding(.horizontal, 8)
120120
.background(backgroundForChatItemType(item.itemType))
121121
.roundedCorner(10, corners: roundedCornersForChatItemType(item.itemType))
122-
.foregroundColor(.white)
122+
.foregroundColor(foregroundForChatItemType(item.itemType))
123+
.tint(tintForChatItemType(item.itemType))
123124
.frame(maxWidth: .infinity, alignment: alignmentForChatItemType(item.itemType))
124125
.textSelection(.enabled)
125126
}
@@ -252,15 +253,35 @@ struct AssistView: View {
252253
switch itemType {
253254
case .input:
254255
.haPrimary
255-
case .output:
256-
.gray
256+
case .output, .typing:
257+
.secondaryBackground
257258
case .error:
258259
.red
259-
case .info, .typing:
260+
case .info:
260261
.gray.opacity(0.5)
261262
}
262263
}
263264

265+
private func foregroundForChatItemType(_ itemType: AssistChatItem.ItemType) -> Color {
266+
switch itemType {
267+
case .input, .error:
268+
.white
269+
case .info:
270+
.secondary
271+
default:
272+
.primary
273+
}
274+
}
275+
276+
private func tintForChatItemType(_ itemType: AssistChatItem.ItemType) -> Color {
277+
switch itemType {
278+
case .input, .error:
279+
.white
280+
default:
281+
.haPrimary
282+
}
283+
}
284+
264285
private func alignmentForChatItemType(_ itemType: AssistChatItem.ItemType) -> Alignment {
265286
switch itemType {
266287
case .input:

Sources/Extensions/Watch/Assist/Views/ChatBubbleView.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ struct ChatBubbleView: View {
1010
AssistTypingIndicator()
1111
.padding(.vertical, Spaces.half)
1212
} else {
13-
Text(item.content)
13+
Text(item.markdown)
1414
}
1515
}
1616
.padding(4)
1717
.padding(.horizontal, 4)
1818
.background(backgroundForChatItemType(item.itemType))
1919
.roundedCorner(6, corners: roundedCornersForChatItemType(item.itemType))
20-
.foregroundColor(.white)
20+
.foregroundColor(foregroundForChatItemType(item.itemType))
21+
.tint(tintForChatItemType(item.itemType))
2122
.frame(maxWidth: .infinity, alignment: alignmentForChatItemType(item.itemType))
2223
.listRowBackground(Color.clear)
2324
.id(item.id)
@@ -28,14 +29,34 @@ struct ChatBubbleView: View {
2829
case .input:
2930
.haPrimary
3031
case .output, .typing:
31-
.gray
32+
.secondaryBackground
3233
case .error:
3334
.red
3435
case .info:
3536
.gray.opacity(0.5)
3637
}
3738
}
3839

40+
private func foregroundForChatItemType(_ itemType: AssistChatItem.ItemType) -> Color {
41+
switch itemType {
42+
case .input, .error:
43+
.white
44+
case .info:
45+
.secondary
46+
default:
47+
.primary
48+
}
49+
}
50+
51+
private func tintForChatItemType(_ itemType: AssistChatItem.ItemType) -> Color {
52+
switch itemType {
53+
case .input, .error:
54+
.white
55+
default:
56+
.haPrimary
57+
}
58+
}
59+
3960
private func alignmentForChatItemType(_ itemType: AssistChatItem.ItemType) -> Alignment {
4061
switch itemType {
4162
case .input:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"colors" : [
3+
{
4+
"color" : {
5+
"color-space" : "srgb",
6+
"components" : {
7+
"alpha" : "1.000",
8+
"blue" : "0xE5",
9+
"green" : "0xE5",
10+
"red" : "0xE5"
11+
}
12+
},
13+
"idiom" : "universal"
14+
},
15+
{
16+
"appearances" : [
17+
{
18+
"appearance" : "luminosity",
19+
"value" : "dark"
20+
}
21+
],
22+
"color" : {
23+
"color-space" : "srgb",
24+
"components" : {
25+
"alpha" : "1.000",
26+
"blue" : "0x28",
27+
"green" : "0x28",
28+
"red" : "0x28"
29+
}
30+
},
31+
"idiom" : "universal"
32+
}
33+
],
34+
"info" : {
35+
"author" : "xcode",
36+
"version" : 1
37+
}
38+
}

Sources/Shared/Assist/AssistChatItem.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ public struct AssistChatItem: Equatable {
99

1010
public var id: String = UUID().uuidString
1111
public let content: String
12+
public var markdown: AttributedString {
13+
var content = (try? AttributedString(
14+
markdown: content,
15+
options: AttributedString
16+
.MarkdownParsingOptions(
17+
interpretedSyntax: .inlineOnlyPreservingWhitespace,
18+
failurePolicy: .returnPartiallyParsedIfPossible
19+
)
20+
)) ?? AttributedString(content)
21+
for run in content.runs where run.attributes.link != nil {
22+
content[run.range].underlineStyle = .single
23+
}
24+
return content
25+
}
26+
1227
public let itemType: ItemType
1328

1429
public enum ItemType {

0 commit comments

Comments
 (0)