Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Img] When I add an image, the onClick doesn't work #121

Open
jordizspmobile opened this issue May 25, 2020 · 2 comments
Open

[Img] When I add an image, the onClick doesn't work #121

jordizspmobile opened this issue May 25, 2020 · 2 comments
Assignees
Labels

Comments

@jordizspmobile
Copy link

jordizspmobile commented May 25, 2020

Hello all!

First at all, I think that library is amazing, but I have an issue with the library, this issue is produced when:

I add an image with <img scr="http://www.example.com/image.jpg" /> all the links with 'a' tags don't work because onClick doesn't call.

Is there any issue or I do something wrong?

My code:

private var bodyTextView = AttributedLabel()


bodyTextView.numberOfLines = 0
bodyTextView.onClick = { label, detection in
     switch detection.type {
           case .link(let url):
                  UIApplication.shared.open(url)
                  break
           case .tag(let tag):
                   if let urlStr = tag.attributes["href"],
                       let url = URL(string: urlStr) {
                       UIApplication.shared.open(url)
                   }
                   break
            default:
                   break
      }
}

let string = "Example text <a href='http://www.example.com/examplelink'>Example link</a><br /><br /><img src='http://www.example.com/image.jpg' />"
let bodyHTML = string.toHtml([
   StyleParams.paragraphFont: UIFont.systemFont(ofSize: 15, weight: .regular),
   StyleParams.paragraphColor: UIColor.black,
   StyleParams.linkFont: UIFont.systemFont(ofSize: 15, weight: .regular),
   StyleParams.linkFontColor: UIColor.red,
   StyleParams.linkFontHightlightColor: UIColor.red
])
bodyTextView.attributeText = bodyHTML
public enum StyleParams {
    //Headers (<h1>..<h5>)
    case titleH1Font // h1
    case titleH1Color
    case titleH1BackgroundColor
    case titleH2Font // h2
    case titleH2Color
    case titleH2BackgroundColor
    case titleH3Font // h3
    case titleH3Color
    case titleH3BackgroundColor
    case titleH4Font // h4
    case titleH4Color
    case titleH4BackgroundColor
    case titleH5Font // h5
    case titleH5Color
    case titleH5BackgroundColor
    //Links (<a>)
    case linkFont
    case linkFontColor
    case linkFontHightlightColor
    case linkBackgroundColor
    //Paragraph (<p>)
    case paragraphFont
    case paragraphColor
    case paragraphBackgroundColor
    //Img
    case imgPlaceholder
}

extension String {
    
    public func toHTML(params: [StyleParams:Any] = [:]) -> AttributedText {
        
        let listHeaders = ["h1", "h2", "h3", "h4", "h5"]
        
        let style = self.style(tags: [
            headerStyle(headers: listHeaders, params: params),
            paragraphStyle(params: params),
            linkStyle(params: params)
        ])
        
        return imageStyle(
            style: style,
            params: params
        ).styleHashtags(
                linkHashtag(params: params)
        ).styleMentions(
                linkStyle(params: params)
        ).styleLinks(
                linkStyle(params: params)
        )

        //OnClick works well without parse to NSAttributeString/NSMutableAttributedString
       /* return style
            .styleHashtags(
                linkHashtag(params: params)
            ).styleMentions(
                linkStyle(params: params)
            ).styleLinks(
                linkStyle(params: params)
            )*/
    }
    
    private func imageStyle() -> Style {
        return Style("img")
    }
    
    private func imageStyle(style: AttributedText, params: [StyleParams: Any] = [:]) -> NSMutableAttributedString {
        
        let mutableAttrStr = NSMutableAttributedString(attributedString: style.attributedString)

        var placeHodler = UIImage(named: "forum_empty_avatar")
        if let imageNamed = params[.imgPlaceholder] as? String {
            placeHodler = UIImage(named: imageNamed)
        }
        
        var locationShift = 0
        for detection in style.detections {
            switch detection.type {
            case .tag(let tag):
                if let imgSrc = tag.attributes["scr"] {
                    
                    let imageView = UIImageView()
                    
                    if let url = URL(string: imgSrc) {
                        imageView.af.setImage(withURL: url, placeholderImage: placeHodler)
                    } else {
                        imageView.image = placeHodler
                    }
                    
                    let textAttachment = NSTextAttachment()
                    textAttachment.image = imageView.image
                    
                    let imageAttrStr = NSAttributedString(attachment: textAttachment)
                    let nsrange = NSRange(detection.range, in: mutableAttrStr.string)
                    mutableAttrStr.insert(imageAttrStr, at: nsrange.location + locationShift)
                    locationShift += 1
                }
                break
            default:
                break
            }
        }
        
        return mutableAttrStr
    }
    
    private func linkHashtag(params: [StyleParams:Any] = [:]) -> Style {
        
        var styleHashtag = Style.font(UIFont.systemFont(ofSize: 15))
        
        if let font = params[.linkFont] as? UIFont {
            styleHashtag = styleHashtag.font(font)
        }
        
        return styleHashtag
    }
    
    private func linkStyle(params: [StyleParams:Any] = [:]) -> Style {
        
        var styleLink = Style("a")
        
        if let font = params[.linkFont] as? UIFont {
            styleLink = styleLink.font(font)
        }
        
        if let color = params[.linkFontColor] as? UIColor {
            styleLink = styleLink.foregroundColor(color, .normal)
        } else {
            fatalError("You need add font color to <a> tag.")
        }
        
        if let color = params[.linkFontHightlightColor] as? UIColor {
            styleLink = styleLink.foregroundColor(color, .highlighted)
        } else {
            fatalError("You need add font hightlight color to <a> tag.")
        }
        
        if let backgroundColor = params[.linkBackgroundColor] as? UIColor {
            styleLink = styleLink.backgroundColor(backgroundColor)
        }
        
        return styleLink
    }
    
    private func paragraphStyle(params: [StyleParams:Any]) -> Style {
        
        var styleLink = Style("p")
        
        if let font = params[.paragraphFont] as? UIFont {
            styleLink = styleLink.font(font)
        }
        
        if let color = params[.paragraphColor] as? UIColor {
            styleLink = styleLink.foregroundColor(color)
        }
        
        if let backgroundColor = params[.paragraphBackgroundColor] as? UIColor {
            styleLink = styleLink.backgroundColor(backgroundColor)
        }
        
        return styleLink
    }
    
    private func headerStyle(headers: [String], params: [StyleParams:Any]) -> Style {
        
        var styleLink = Style("h1")
        for header in headers {
            styleLink = Style(header)
            switch header {
                case "h1": styleLink = headerH1Style(style: styleLink, params: params)
                    break
                case "h2": styleLink = headerH2Style(style: styleLink, params: params)
                    break
                case "h3": styleLink = headerH3Style(style: styleLink, params: params)
                    break
                case "h4": styleLink = headerH4Style(style: styleLink, params: params)
                    break
                case "h5": styleLink = headerH5Style(style: styleLink, params: params)
                    break
                default:  styleLink = headerH5Style(style: styleLink, params: params)
                    break
            }
        }
        
        return styleLink
    }
    
    private func headerH1Style(style: Style, params: [StyleParams:Any]) -> Style {
        
        var style = style
        if let font = params[.titleH1Font] as? UIFont {
            style = style.font(font)
        }
        
        if let color = params[.titleH1Color] as? UIColor {
            style = style.foregroundColor(color)
        }
        
        if let color = params[.titleH1BackgroundColor] as? UIColor {
            style = style.backgroundColor(color)
        }
        
        return style
    }
}
@jordizspmobile jordizspmobile changed the title [Img] When added image the onClick doesn't work [Img] When I add an image, the onClick doesn't work May 25, 2020
@psharanda
Copy link
Owner

Looks like connected with this one #130

@psharanda psharanda self-assigned this Oct 25, 2020
@psharanda psharanda added the bug label Oct 25, 2020
@tarun-personatech
Copy link

@jordizspmobile I just need to show the image and do not need the tap. In that case, your code should download the image and show it but I was wondering does it ever show the image.
Because when the attributed string is built the image is not present, it is being downloaded, and after that textAttachment's image is set. By this time the attributed string is already shown. Setting the image on textAttachment after that has no effect in my case.
How do we update the textAttachment after the image is downloaded?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants
@psharanda @jordizspmobile @tarun-personatech and others