Atributika icon indicating copy to clipboard operation
Atributika copied to clipboard

Preliminary SwiftUI support

Open rivera-ernesto opened this issue 4 years ago • 5 comments

For now an AttributtedLabel SwiftUI wrapper in the Demo project that allows full customization using an optional configureLabel block property.

Usage requires to set a maxWidth (default value 300) and requires adding the .fixedSize(horizontal: true, vertical: true) modifier:

AttributedLabelView(attributedText: "Denny JA: Dengan RT ini, anda ikut memenangkan Jokowi-JK. Pilih pemimpin yg bisa dipercaya (Jokowi) dan pengalaman (JK). #DJoJK"
    .style(tags: link)
    .styleHashtags(link)
    .styleMentions(link)
    .styleLinks(link)
    .styleAll(all), configureLabel: configureLabel, maxWidth: geometry.size.width)
    .fixedSize(horizontal: true, vertical: true)

Related to #103 and #113.

rivera-ernesto avatar May 15 '20 13:05 rivera-ernesto

Hi, Looks like a really good start! Thanks for contributing 👍 Going to review in depth over weekend

psharanda avatar May 15 '20 15:05 psharanda

For my project I am embedding the view inside a wrapping SwiftUI class to accept regular String text, hide setting .styles, configuring the label and hide the ugly but needed .fixedSize().

The result is that I can now just use MessageBodyLabel(text: "Any complex string").

struct MessageBodyLabel: View
{
    var text: String
    var textColor = UIColor(named: "body")!
    @State var maxWidth: CGFloat = 200
    
    private func configureLabel(_ label: AttributedLabel)
    {
        label.numberOfLines = 0
        label.font = .inter()
        label.textColor = self.textColor
    }
    
    private let allStyle = Style()
    private let linkStyle = Style("a").foregroundColor(.appTint, .normal)//.foregroundColor(.brown, .highlighted)
    private let header1Style = Style("h1").font(.inter(size: 19, weight: .bold))
    private let header2Style = Style("h2").font(.inter(size: 17, weight: .bold))
    private let header3Style = Style("h3").font(.inter(size: 15, weight: .bold))
    private let boldStyle = Style("strong").font(.inter(weight: .bold))
    private let italicStyle = Style("em").font(.inter(italic: true))
    private let codeStyle = Style("code").font(UIFont(name: "Menlo", size: 13)!).foregroundColor(.systemPink)
    private let listStyle = Style("li").paragraphStyle({
        let bullet = "• "
        let indentation: CGFloat = (bullet as NSString).size(withAttributes: [NSAttributedString.Key.font: UIFont.inter()]).width
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: indentation, options: [NSTextTab.OptionKey: Any]())]
        paragraphStyle.defaultTabInterval = indentation
        paragraphStyle.headIndent = indentation
        return paragraphStyle
    }())
    
    private var attributedText: AttributedText
    {
        var listCounter: Int!
        let transformers = [
            TagTransformer.brTransformer,
            TagTransformer(tagName: "ol", tagType: .start) { _ in
                listCounter = 0
                return ""
            },
            TagTransformer(tagName: "ol", tagType: .end) { _ in
                listCounter = nil
                return ""
            },
            TagTransformer(tagName: "li", tagType: .start) { tag in
                guard listCounter != nil else
                {
                    return "• "
                }
                listCounter += 1
                return "\(listCounter!). "
            }
        ]
        
        return self.text
            .style(tags: self.linkStyle,
                   self.header1Style,
                   self.header2Style,
                   self.header3Style,
                   self.boldStyle,
                   self.italicStyle,
                   self.codeStyle,
                   self.listStyle, transformers: transformers)
            .styleLinks(self.linkStyle)
            .stylePhoneNumbers(self.linkStyle)
            .styleAll(self.allStyle)
    }
    
    var body: some View
    {
        AttributedLabelView(attributedText: self.attributedText,
                            configureLabel: self.configureLabel,
                            maxWidth: self.maxWidth)
            .fixedSize(horizontal: true, vertical: true)
    }
}

rivera-ernesto avatar May 15 '20 19:05 rivera-ernesto

You can play with Xcode Live Previews. It works pretty well, so I didn't add an extra tab to the Demo app.

rivera-ernesto avatar May 15 '20 19:05 rivera-ernesto

can add sample to demo app?

sonysm avatar Feb 02 '22 08:02 sonysm

Hello, is Atribuika compatible with SwiftUI 2? The above examples aren't working in it.

rak-sascha-github avatar Mar 14 '22 08:03 rak-sascha-github

I've added SwiftUI examples in the recent release.

psharanda avatar Jun 04 '23 10:06 psharanda