Skip to content

Commit d32ea63

Browse files
Added markdown support (#466)
1 parent 3f96684 commit d32ea63

14 files changed

+304
-35
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
33

44
# Upcoming
55

6-
### 🔄 Changed
6+
### ✅ Added
7+
- Added markdown support (enabled by default)
78

89
# [4.51.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.51.0)
910
_March 26, 2024_

Sources/StreamChatSwiftUI/ChatChannel/MessageList/LinkAttachmentView.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,22 @@ public struct LinkAttachmentContainer<Factory: ViewFactory>: View {
4949

5050
let availableWidth = width - 4 * padding
5151
let size = message.adjustedText.frameSize(maxWidth: availableWidth)
52-
LinkTextView(
53-
message: message,
54-
width: availableWidth,
55-
textColor: UIColor(textColor(for: message))
56-
)
57-
.frame(width: availableWidth, height: size.height)
58-
.standardPadding()
52+
53+
if #available(iOS 15, *) {
54+
HStack {
55+
StreamTextView(message: message)
56+
.standardPadding()
57+
Spacer()
58+
}
59+
} else {
60+
LinkTextView(
61+
message: message,
62+
width: availableWidth,
63+
textColor: UIColor(textColor(for: message))
64+
)
65+
.frame(width: availableWidth, height: size.height)
66+
.standardPadding()
67+
}
5968

6069
if !message.linkAttachments.isEmpty {
6170
LinkAttachmentView(

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageListConfig.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public struct MessageListConfig {
2929
messageListAlignment: MessageListAlignment = .standard,
3030
uniqueReactionsEnabled: Bool = false,
3131
localLinkDetectionEnabled: Bool = true,
32-
isMessageEditedLabelEnabled: Bool = true
32+
isMessageEditedLabelEnabled: Bool = true,
33+
markdownSupportEnabled: Bool = true
3334
) {
3435
self.messageListType = messageListType
3536
self.typingIndicatorPlacement = typingIndicatorPlacement
@@ -52,6 +53,7 @@ public struct MessageListConfig {
5253
self.uniqueReactionsEnabled = uniqueReactionsEnabled
5354
self.localLinkDetectionEnabled = localLinkDetectionEnabled
5455
self.isMessageEditedLabelEnabled = isMessageEditedLabelEnabled
56+
self.markdownSupportEnabled = markdownSupportEnabled
5557
}
5658

5759
public let messageListType: MessageListType
@@ -75,6 +77,7 @@ public struct MessageListConfig {
7577
public let uniqueReactionsEnabled: Bool
7678
public let localLinkDetectionEnabled: Bool
7779
public let isMessageEditedLabelEnabled: Bool
80+
public let markdownSupportEnabled: Bool
7881
}
7982

8083
/// Contains information about the message paddings.

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageView.swift

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,12 @@ public struct EmojiTextView<Factory: ViewFactory>: View {
224224

225225
struct StreamTextView: View {
226226

227-
@Injected(\.utils) var utils
228227
@Injected(\.fonts) var fonts
229228

230229
var message: ChatMessage
231230

232231
var body: some View {
233-
if #available(iOS 15, *), utils.messageListConfig.localLinkDetectionEnabled {
232+
if #available(iOS 15, *) {
234233
LinkDetectionTextView(message: message)
235234
} else {
236235
Text(message.adjustedText)
@@ -245,40 +244,85 @@ struct LinkDetectionTextView: View {
245244

246245
@Injected(\.colors) var colors
247246
@Injected(\.fonts) var fonts
247+
@Injected(\.utils) var utils
248248

249249
var message: ChatMessage
250250

251-
var text: String {
252-
message.adjustedText
251+
var text: LocalizedStringKey {
252+
LocalizedStringKey(message.adjustedText)
253253
}
254254

255-
@State var displayedText: AttributedString
255+
@State var displayedText: AttributedString?
256256

257257
@State var linkDetector = TextLinkDetector()
258258

259+
@State var tintColor = InjectedValues[\.colors].tintColor
260+
259261
init(message: ChatMessage) {
260262
self.message = message
261-
_displayedText = State(initialValue: AttributedString(message.adjustedText))
263+
}
264+
265+
private var markdownEnabled: Bool {
266+
utils.messageListConfig.markdownSupportEnabled
262267
}
263268

264269
var body: some View {
265-
Text(displayedText)
266-
.foregroundColor(textColor(for: message))
267-
.font(fonts.body)
268-
.onAppear {
269-
let attributedText = NSMutableAttributedString(
270-
string: text,
271-
attributes: [
272-
.foregroundColor: textColor(for: message),
273-
.font: fonts.body
274-
]
275-
)
270+
Group {
271+
if let displayedText {
272+
Text(displayedText)
273+
} else if markdownEnabled {
274+
Text(text)
275+
} else {
276+
Text(message.adjustedText)
277+
}
278+
}
279+
.foregroundColor(textColor(for: message))
280+
.font(fonts.body)
281+
.tint(tintColor)
282+
.onAppear {
283+
guard utils.messageListConfig.localLinkDetectionEnabled else { return }
284+
var attributes: [NSAttributedString.Key: Any] = [
285+
.foregroundColor: textColor(for: message),
286+
.font: fonts.body
287+
]
288+
289+
let additional = utils.messageListConfig.messageDisplayOptions.messageLinkDisplayResolver(message)
290+
for (key, value) in additional {
291+
if key == .foregroundColor, let value = value as? UIColor {
292+
tintColor = Color(value)
293+
} else {
294+
attributes[key] = value
295+
}
296+
}
297+
298+
let attributedText = NSMutableAttributedString(
299+
string: message.adjustedText,
300+
attributes: attributes
301+
)
276302

277-
linkDetector.links(in: text).forEach { textLink in
278-
attributedText.addAttribute(.link, value: textLink.url, range: textLink.range)
303+
var containsLinks = false
304+
let range = NSRange(location: 0, length: message.adjustedText.utf16.count)
305+
linkDetector.links(in: message.adjustedText).forEach { textLink in
306+
let pattern = "\\[([^\\]]+)\\]\\(\(textLink.originalText)\\)"
307+
if let regex = try? NSRegularExpression(pattern: pattern) {
308+
containsLinks = (regex.firstMatch(
309+
in: message.adjustedText,
310+
options: [],
311+
range: range
312+
) == nil) || !markdownEnabled
313+
} else {
314+
containsLinks = true
279315
}
280316

317+
if !message.adjustedText.contains("](\(textLink.originalText))") {
318+
containsLinks = true
319+
}
320+
attributedText.addAttribute(.link, value: textLink.url, range: textLink.range)
321+
}
322+
323+
if containsLinks {
281324
self.displayedText = AttributedString(attributedText)
282325
}
326+
}
283327
}
284328
}

0 commit comments

Comments
 (0)