GetStream / stream-chat-swiftui

SwiftUI Chat SDK ➜ Stream Chat 💬
https://getstream.io/chat/sdk/swiftui/
Other
336 stars 81 forks source link

How to customize link text attributes? #79

Closed zrxq closed 2 years ago

zrxq commented 2 years ago

I'd like to customize parsed URL text color and probably other attributes, like font weight. How do I approach this?

martinmitrevski commented 2 years ago

hey @zrxq,

Our link attachment text view is using the tint color for the links by default. It's a SwiftUI wrapper of a UITextView.

There are few options here:

Let me know what works best for you.

Regards, Martin

zrxq commented 2 years ago

Hey Martin,

Thanks for the prompt reply!

All options seem viable for different cases, I actually just wanted to point out that having an option to configure the color would probably make the SDK more awesome. Sorry for the initial post wording. I think it's a rather common use case to have varying background color for messages depending on the author. In the demo link attachments have static color, independent of the sender (me/them) which is not always desirable from the UX perspective. As soon as the SDK user somehow customised the background color to vary for current/other user, the problem with link having a static color arises, ie. one would probably wan't a highly contrast color for an actionable UI element (a link) which depends on being able to alter the color in accord with the background. The actual link text component LinkTextView is a bit too deep in the view hierarchy to try and access using SwiftUI view modifiers so yea, providing a configuration property could be a good idea in my opinion.

martinmitrevski commented 2 years ago

Thanks @zrxq for the clarification. Basically, you would need sth like this:

var messageLinkDisplayResolver: (ChatMessage) -> [NSAttributedString.Key: Any]

In your own implementation, you could check the message for the additional logic and provide different colors / fonts per user. Would this help?

Another alternative - we can also expose LinkTextView as a swappable component if it helps more.

Let me know your thoughts.

zrxq commented 2 years ago

Either would help to solve the task in question (given the DI works perfectly and the resolver is fully aware of the context, including being in a quote etc), I believe it worth considering which solution better suits your existing architecture.

I, personally, would first try and draw a line marking the max amount of customization I would let the user do before giving up and opting for a fully custom implementation of the top level view factory returnee. If I wanted the user to be able to customize literally everything then probably making every component swappable/injectable via the factory or perhaps template arguments, or something, would look like the way to go. This may seem extreme, but then again, there is a number of popular chat platform UX designers may refer to when working on the experience, e.g. Stream used to have an iMessage clone example, someone may want to have Slack/Twitch/Instagram/whatever as their UX template, each of them have slightly different approache to grouping messages, displaying quotes, etcetera which leads to a situation when either you have to make the UI lib deeply customizable, or draw an explicit line somewhere much closer to the surface, e.g. "you can have whatever chat you want built on Stream SwiftUI as long as it feels like Whatsapp or whatever". My use case unfortunately requires me to reimplement, as opposed to customize, almost everything, borrowing heavily from the existing viewmodel/controller logic, and I imagine that if the SDK allowed to mix and match the existing UI components with custom ones more, this task would be somewhat easier and more superficial. Anyway, obviously I have no idea what other customers normally need and want, so, just a data point.

martinmitrevski commented 2 years ago

Thanks @zrxq for the feedback. Both approaches fit in our existing architecture. We will go with the resolver, since customers shouldn't re-implement the link text view just for the link attributes. We will let you know when this is available.

About the other part of the discussion, yes, the initial template is based on messaging chat apps like iMessage and WhatsApp, but we are actually expanding to livestream apps like Twitch (we also have a clone for this) and other types of chat experiences. Therefore, our long term goal is to try to be deeply customizable for most types of chat experiences. (Of course, that depends on the type of customers we have and the requirements they have.)

Curious about the type of chat experience you are working on - which popular app is it similar too? Your feedback will help us in improving our customization options, so if you have some time, feel free to drop me an email with more details.

zrxq commented 2 years ago

It's similar to Telegram, structure and UI-wise, but kind of slapped on top of a streaming experience, not entirely unlike Twitch or YouTube. :)

martinmitrevski commented 2 years ago

Sounds cool, thanks for the explanation @zrxq. Btw, the change is now available on our main branch. Here's the usage:

let messageDisplayOptions = MessageDisplayOptions(messageLinkDisplayResolver: { message in
let color = message.isSentByCurrentUser ? UIColor.red : UIColor.green
     return [
                NSAttributedString.Key.foregroundColor: color
    ]
})
let messageListConfig = MessageListConfig(messageDisplayOptions: messageDisplayOptions)
let utils = Utils(messageListConfig: messageListConfig)

let streamChat = StreamChat(chatClient: chatClient, utils: utils)