@@ -16,19 +16,22 @@ public struct MessageView<Factory: ViewFactory>: View {
1616 public var message : ChatMessage
1717 public var contentWidth : CGFloat
1818 public var isFirst : Bool
19+ public var translationLanguage : TranslationLanguage ?
1920 @Binding public var scrolledId : String ?
2021
2122 public init (
2223 factory: Factory ,
2324 message: ChatMessage ,
2425 contentWidth: CGFloat ,
2526 isFirst: Bool ,
26- scrolledId: Binding < String ? >
27+ scrolledId: Binding < String ? > ,
28+ translationLanguage: TranslationLanguage ? = nil
2729 ) {
2830 self . factory = factory
2931 self . message = message
3032 self . contentWidth = contentWidth
3133 self . isFirst = isFirst
34+ self . translationLanguage = translationLanguage
3235 _scrolledId = scrolledId
3336 }
3437
@@ -75,7 +78,8 @@ public struct MessageView<Factory: ViewFactory>: View {
7578 message: message,
7679 isFirst: isFirst,
7780 availableWidth: contentWidth,
78- scrolledId: $scrolledId
81+ scrolledId: $scrolledId,
82+ translationLanguage: translationLanguage
7983 )
8084 )
8185 } else {
@@ -93,7 +97,8 @@ public struct MessageView<Factory: ViewFactory>: View {
9397 message: message,
9498 isFirst: isFirst,
9599 availableWidth: contentWidth,
96- scrolledId: $scrolledId
100+ scrolledId: $scrolledId,
101+ translationLanguage: translationLanguage
97102 )
98103 )
99104 }
@@ -110,6 +115,7 @@ public struct MessageTextView<Factory: ViewFactory>: View {
110115 private let factory : Factory
111116 private let message : ChatMessage
112117 private let isFirst : Bool
118+ private let translationLanguage : TranslationLanguage ?
113119 private let leadingPadding : CGFloat
114120 private let trailingPadding : CGFloat
115121 private let topPadding : CGFloat
@@ -120,7 +126,8 @@ public struct MessageTextView<Factory: ViewFactory>: View {
120126 factory: Factory ,
121127 message: ChatMessage ,
122128 isFirst: Bool ,
123- scrolledId: Binding < String ? >
129+ scrolledId: Binding < String ? > ,
130+ translationLanguage: TranslationLanguage ?
124131 ) {
125132 @Injected ( \. tokens) var tokens
126133 self . init (
@@ -131,10 +138,11 @@ public struct MessageTextView<Factory: ViewFactory>: View {
131138 trailingPadding: tokens. spacingSm,
132139 topPadding: tokens. spacingXs,
133140 bottomPadding: tokens. spacingXs,
134- scrolledId: scrolledId
141+ scrolledId: scrolledId,
142+ translationLanguage: translationLanguage
135143 )
136144 }
137-
145+
138146 public init (
139147 factory: Factory ,
140148 message: ChatMessage ,
@@ -143,11 +151,13 @@ public struct MessageTextView<Factory: ViewFactory>: View {
143151 trailingPadding: CGFloat ,
144152 topPadding: CGFloat ,
145153 bottomPadding: CGFloat ,
146- scrolledId: Binding < String ? >
154+ scrolledId: Binding < String ? > ,
155+ translationLanguage: TranslationLanguage ?
147156 ) {
148157 self . factory = factory
149158 self . message = message
150159 self . isFirst = isFirst
160+ self . translationLanguage = translationLanguage
151161 self . leadingPadding = leadingPadding
152162 self . trailingPadding = trailingPadding
153163 self . topPadding = topPadding
@@ -160,12 +170,15 @@ public struct MessageTextView<Factory: ViewFactory>: View {
160170 alignment: message. alignmentInBubble,
161171 spacing: 0
162172 ) {
163- factory. makeStreamTextView ( options: . init( message: message) )
164- . padding ( . leading, leadingPadding)
165- . padding ( . trailing, trailingPadding)
166- . padding ( . top, topPadding)
167- . padding ( . bottom, bottomPadding)
168- . fixedSize ( horizontal: false , vertical: true )
173+ factory. makeStreamTextView ( options: . init(
174+ message: message,
175+ translationLanguage: translationLanguage
176+ ) )
177+ . padding ( . leading, leadingPadding)
178+ . padding ( . trailing, trailingPadding)
179+ . padding ( . top, topPadding)
180+ . padding ( . bottom, bottomPadding)
181+ . fixedSize ( horizontal: false , vertical: true )
169182 }
170183 . modifier (
171184 factory. styles. makeMessageViewModifier (
@@ -220,117 +233,34 @@ public struct EmojiTextView<Factory: ViewFactory>: View {
220233}
221234
222235struct StreamTextView : View {
223- @Injected ( \. fonts) var fonts
224-
225- let message : ChatMessage
226- private let adjustedText : String
227-
228- init ( message: ChatMessage ) {
229- self . message = message
230- adjustedText = message. adjustedText
231- }
232-
233- var body : some View {
234- if #available( iOS 15 , * ) {
235- LinkDetectionTextView ( message: message)
236- } else {
237- Text ( adjustedText)
238- . foregroundColor ( textColor ( for: message) )
239- . font ( fonts. body)
240- }
241- }
242- }
243-
244- @available ( iOS 15 , * )
245- public struct LinkDetectionTextView : View {
246236 @Environment ( \. layoutDirection) var layoutDirection
247- @Environment ( \. channelTranslationLanguage) var translationLanguage
248- @Environment ( \. messageViewModel) var messageViewModel
249-
250237 @Injected ( \. colors) var colors
251238 @Injected ( \. fonts) var fonts
252- @Injected ( \. utils) var utils
253-
254- var message : ChatMessage
255239
256- // The translations store is used to detect changes so the textContent is re-rendered.
257- // The @Environment(\.messageViewModel) is not reactive like @EnvironmentObject.
258- // TODO: On v5 the TextView should be refactored and not depend directly on the view model.
259- @ObservedObject var originalTranslationsStore = InjectedValues [ \. utils] . originalTranslationsStore
240+ let message : ChatMessage
241+ let textContent : String
242+ let translationLanguage : TranslationLanguage ?
260243
261- @State var text : AttributedString ?
262- @State var linkDetector = TextLinkDetector ( )
263- @State var tintColor = Color ( InjectedValues [ \. colors] . accentPrimary)
264-
265- public init (
266- message: ChatMessage
267- ) {
244+ init ( message: ChatMessage , translationLanguage: TranslationLanguage ? ) {
268245 self . message = message
246+ self . textContent = message. textContent ( for: translationLanguage) ?? message. adjustedText
247+ self . translationLanguage = translationLanguage
269248 }
270-
271- public var body : some View {
272- Group {
273- Text ( text ?? displayText)
274- }
275- . foregroundColor ( textColor ( for: message) )
276- . font ( fonts. body)
277- . tint ( tintColor)
278- . onChange ( of: message) { message in
279- messageViewModel? . message = message
280- text = displayText
281- }
282- }
283-
284- var displayText : AttributedString {
285- let text = messageViewModel? . textContent ?? message. text
286249
287- // Markdown
288- let attributes = AttributeContainer ( )
289- . foregroundColor ( textColor ( for: message) )
290- . font ( fonts. body)
291- var attributedString : AttributedString
292- if utils. messageListConfig. markdownSupportEnabled {
293- attributedString = utils. markdownFormatter. format (
294- text,
295- attributes: attributes,
296- layoutDirection: layoutDirection
250+ var body : some View {
251+ if #available( iOS 15 , * ) {
252+ let attributedText = message. attributedTextContent (
253+ layoutDirection: layoutDirection,
254+ translationLanguage: translationLanguage
297255 )
256+ Text ( attributedText)
257+ . foregroundColor ( textColor ( for: message) )
258+ . font ( fonts. body)
259+ . tint ( Color ( colors. accentPrimary) )
298260 } else {
299- attributedString = AttributedString ( message. adjustedText, attributes: attributes)
300- }
301- // Links and mentions
302- if utils. messageListConfig. localLinkDetectionEnabled {
303- for user in message. mentionedUsers {
304- let mention = " @ \( user. name ?? user. id) "
305- let ranges = attributedString. ranges ( of: mention, options: [ . caseInsensitive] )
306- for range in ranges {
307- if let messageId = message. messageId. addingPercentEncoding ( withAllowedCharacters: . urlPathAllowed) ,
308- let url = URL ( string: " getstream://mention/ \( messageId) / \( user. id) " ) {
309- attributedString [ range] . link = url
310- }
311- }
312- }
313- for link in linkDetector. links ( in: String ( attributedString. characters) ) {
314- if let attributedStringRange = Range ( link. range, in: attributedString) {
315- attributedString [ attributedStringRange] . link = link. url
316- }
317- }
318- }
319- // Finally change attributes for links (markdown links, text links, mentions)
320- var linkAttributes = utils. messageListConfig. messageDisplayOptions. messageLinkDisplayResolver ( message)
321- if !linkAttributes. isEmpty {
322- var linkAttributeContainer = AttributeContainer ( )
323- if let uiColor = linkAttributes [ . foregroundColor] as? UIColor {
324- linkAttributeContainer = linkAttributeContainer. foregroundColor ( Color ( uiColor: uiColor) )
325- linkAttributes. removeValue ( forKey: . foregroundColor)
326- }
327- linkAttributeContainer. merge ( AttributeContainer ( linkAttributes) )
328- for (value, range) in attributedString. runs [ \. link] {
329- guard value != nil else { continue }
330- attributedString [ range] . mergeAttributes ( linkAttributeContainer)
331- }
261+ Text ( textContent)
262+ . foregroundColor ( textColor ( for: message) )
263+ . font ( fonts. body)
332264 }
333-
334- return attributedString
335265 }
336266}
0 commit comments