0

These are my datasSource and delegate methods for my chat:

func messageForItem(at indexPath: IndexPath, in _: MessagesCollectionView) -> MessageType {
    viewModel.message(at: indexPath) //here is returnd object that conform to protocl MessageType, one of its properties is messgaeKind where is defined attributedText(attributedString)
}

func enabledDetectors(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> [DetectorType] {
    [.url, .phoneNumber]
}

func detectorAttributes(
    for _: DetectorType,
    and message: MessageType,
    at _: IndexPath
) -> [NSAttributedString.Key: Any] {
    [.underlineStyle: 1, .foregroundColor: isFromCurrentSender(message: message) ? UIColor.white : UIColor.black]
}

And this is how it looks now:

enter image description here

I have tried to replace attributedString for messageKind like this:

//This is part of MessageType object. One of required properties is `var kind: MessageKind`:
var kind: MessageKind {
    return .attributedText(attributedString.prettyLinked)
}


**attributedString** - ✅ it works, links are detected

Moze tez byc kilka linkow w wiadomosci, pierwszy https://joytst.page.link/g9XaJeuffcH7koXk9?title=Głosowanie%20ze%20spacją i drugi tez obok https://joytst.page.link/g9XaJeuffcH7koXk9?title=Głosowanie i jeszcze koniec wiadomosci!{
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x109215210> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}

attributedString.prettyLinked - ❌ it doesn't work, links are not detected

Moze tez byc kilka linkow w wiadomosci, pierwszy {
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x109215210> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}super link {
    NSLink = "https://joytst.page.link/g9XaJeuffcH7koXk9?title=G\U0142osowanie%20ze%20spacj\U0105";
} i drugi tez obok {
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x109215210> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}super link {
    NSLink = "https://joytst.page.link/g9XaJeuffcH7koXk9?title=G\U0142osowanie";
} i jeszcze koniec wiadomosci!{
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x109215210> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}

attributedString.prettyLinked - ✅ links are detected, but every link is www.apple.com (not the real link).⁉️

Moze tez byc kilka linkow w wiadomosci, pierwszy {
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x12f3120c0> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}http://www.apple.com{
    NSLink = "https://joytst.page.link/g9XaJeuffcH7koXk9?title=G\U0142osowanie%20ze%20spacj\U0105";
} i drugi tez obok {
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x12f3120c0> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}http://www.apple.com{
    NSLink = "https://joytst.page.link/g9XaJeuffcH7koXk9?title=G\U0142osowanie";
} i jeszcze koniec wiadomosci!{
    NSColor = "UIExtendedSRGBColorSpace 0.2 0.2 0.2 1";
    NSFont = "<UICTFont: 0x12f3120c0> font-family: \"Poppins-Regular\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
}

where:

extension NSAttributedString {
    var prettyLinked: NSAttributedString {
        let mutableString = NSMutableAttributedString(attributedString: self)
        do {
            let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
            let fullRange = NSRange(location: 0, length: string.utf16.count)
            let matches = detector.matches(in: string, range: fullRange)
            matches.reversed().forEach { match in
                let range = match.range
                let link = (string as NSString).substring(with: range)
                let prettyLink = NSAttributedString(string: "super link ", attributes: [.link: link])
                mutableString.replaceCharacters(in: range, with: prettyLink)
            }
        } catch {}
        return NSAttributedString(attributedString: mutableString)
    }
}

The result is like:

enter image description here

But it is not tappable, after that change. Why?

What do I want to achieve is to replace that urls with any string, for example here is super link . And then didSelectUrl is called as always. Is it possible with MessageKit?

halfer
  • 19,824
  • 17
  • 99
  • 186
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358

1 Answers1

0

Based on the source code: https://github.com/MessageKit/MessageKit/blob/main/Sources/Views/MessageLabel.swift#L54 the message displayed on MessageLabel (UILabel) and it keeps a list of urlAttributes itself to detect when you tap on a link in that view, so you need to set those attributes manually

public func setAttributes(_ attributes: [NSAttributedString.Key: Any], detector: DetectorType)

As the class track if the user tap on MessageLabel (View) and calls delegate?.didSelectURL(url) after recognizing which part of the text was tapped in this function:

private func handleGesture(for detectorType: DetectorType, value: MessageTextCheckingType)

(https://github.com/MessageKit/MessageKit/blob/main/Sources/Views/MessageLabel.swift#L477)

Oleg
  • 591
  • 5
  • 14
  • Ok, I understand your point of view but... title for that link is not an attribute for it. Am I right? I can set color, underline, font etc... but not the title itself. – Bartłomiej Semańczyk Feb 13 '23 at 11:50
  • when you change the text to another one, you need to update the `urlAttributes` property in `MessageLabel`, otherwise when the user taps `MessageLabel` will not understand what action to trigger inside `handleGesture()` function here: https://github.com/MessageKit/MessageKit/blob/main/Sources/Views/MessageLabel.swift#L142. – Oleg Feb 13 '23 at 15:40
  • Ok, but I dont understand one thing. I prepare NSAttributedString (as associated type of MessageKind enum) BEFORE i return it in dataSource method. So I do not change it AFTER it is assigned to messageLabel, but BEFORE. So, does it still matter? – Bartłomiej Semańczyk Feb 13 '23 at 15:50
  • property `var attributedText: NSAttributedString?` https://github.com/MessageKit/MessageKit/blob/main/Sources/Views/MessageLabel.swift#L72 is calling `setTextStorage(attributedText, shouldParse: true)` (focus on `shouldParse=true`). If you check what this function does, it will clear up and generate links detectors https://github.com/MessageKit/MessageKit/blob/main/Sources/Views/MessageLabel.swift#L256 and those detectors will be used to find the url when user tap on view. – Oleg Feb 14 '23 at 07:29
  • Yes, I saw it... but for some reason it doesnt detect my new attributedString. I updated the question with working example attributedString before change, and non working after change. – Bartłomiej Semańczyk Feb 14 '23 at 08:09
  • I see there very weird behaviour. When I replace my links with `url` title it works, linkes are detected, but the ones from titles, not real links. Why? – Bartłomiej Semańczyk Feb 14 '23 at 08:13
  • probably because if you don't specify attributes via setAttributes, it will just parse text and detects link with regex.. – Oleg Feb 14 '23 at 15:39