diff options
Diffstat (limited to 'iosApp/iosApp/Shared/HyperlinkText.swift')
-rw-r--r-- | iosApp/iosApp/Shared/HyperlinkText.swift | 186 |
1 files changed, 73 insertions, 113 deletions
diff --git a/iosApp/iosApp/Shared/HyperlinkText.swift b/iosApp/iosApp/Shared/HyperlinkText.swift index 69c758b..a735f8d 100644 --- a/iosApp/iosApp/Shared/HyperlinkText.swift +++ b/iosApp/iosApp/Shared/HyperlinkText.swift @@ -15,129 +15,89 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import SwiftUI -import SwiftUIFlowLayout +import Foundation +import UIKit -// Source: https://swiftuirecipes.com/blog/hyperlinks-in-swiftui-text -struct HyperlinkText: View { - private let pairs: [StringWithAttributes] - - init(_ attributedString: NSAttributedString) { - pairs = attributedString.stringsWithAttributes +// Source: https://stackoverflow.com/a/50272137 +extension UIColor { + enum HexFormat { + case RGB + case ARGB + case RGBA + case RRGGBB + case AARRGGBB + case RRGGBBAA } - - init?(html: String) { - if let data = html.data(using: .utf8), - let attributedString = try? NSAttributedString(data: data, - options: [.documentType: NSAttributedString.DocumentType.html], - documentAttributes: nil) { - self.init(attributedString) - } else { - return nil - } - } - - var body: some View { - FlowLayout(mode: .vstack, - binding: .constant(false), - items: pairs, - itemSpacing: 0) { pair in - if let link = pair.attrs[.link], - let url = link as? URL { - Text(pair) - .onTapGesture { - if UIApplication.shared.canOpenURL(url) { - UIApplication.shared.open(url) - } - } - } else { - Text(pair) - } - } - } -} -struct StringWithAttributes: Hashable, Identifiable { - let id = UUID() - let string: String - let attrs: [NSAttributedString.Key: Any] - - static func == (lhs: StringWithAttributes, rhs: StringWithAttributes) -> Bool { - lhs.id == rhs.id - } - - func hash(into hasher: inout Hasher) { - hasher.combine(id) + enum HexDigits { + case d3, d4, d6, d8 } -} -extension NSAttributedString { - var stringsWithAttributes: [StringWithAttributes] { - var attributes = [StringWithAttributes]() - enumerateAttributes(in: NSRange(location: 0, length: length), options: []) { (attrs, range, _) in - let string = attributedSubstring(from: range).string - attributes.append(StringWithAttributes(string: string, attrs: attrs)) - } - return attributes - } -} + func hexString(_ format: HexFormat = .RRGGBBAA) -> String { + let maxi = [.RGB, .ARGB, .RGBA].contains(format) ? 16 : 256 -extension Text { - init(_ singleAttribute: StringWithAttributes) { - let string = singleAttribute.string - let attrs = singleAttribute.attrs - var text = Text(string) - - /*if let font = attrs[.font] as? UIFont { - text = text.font(.init(font)) - } - - if let color = attrs[.foregroundColor] as? UIColor { - text = text.foregroundColor(Color(color)) - }*/ - - if let kern = attrs[.kern] as? CGFloat { - text = text.kerning(kern) - } - - if #available(iOS 14.0, *) { - if let tracking = attrs[.tracking] as? CGFloat { - text = text.tracking(tracking) - } + func toI(_ f: CGFloat) -> Int { + return min(maxi - 1, Int(CGFloat(maxi) * f)) } - - if let strikethroughStyle = attrs[.strikethroughStyle] as? NSNumber, strikethroughStyle != 0 { - if let strikethroughColor = (attrs[.strikethroughColor] as? UIColor) { - text = text.strikethrough(true, color: Color(strikethroughColor)) - } else { - text = text.strikethrough(true) - } - } - - if let underlineStyle = attrs[.underlineStyle] as? NSNumber, - underlineStyle != 0 { - if let underlineColor = (attrs[.underlineColor] as? UIColor) { - text = text.underline(true, color: Color(underlineColor)) - } else { - text = text.underline(true) - } - } - - if let baselineOffset = attrs[.baselineOffset] as? NSNumber { - text = text.baselineOffset(CGFloat(baselineOffset.floatValue)) + + var r: CGFloat = 0 + var g: CGFloat = 0 + var b: CGFloat = 0 + var a: CGFloat = 0 + + self.getRed(&r, green: &g, blue: &b, alpha: &a) + + let ri = toI(r) + let gi = toI(g) + let bi = toI(b) + let ai = toI(a) + + switch format { + case .RGB: return String(format: "#%X%X%X", ri, gi, bi) + case .ARGB: return String(format: "#%X%X%X%X", ai, ri, gi, bi) + case .RGBA: return String(format: "#%X%X%X%X", ri, gi, bi, ai) + case .RRGGBB: return String(format: "#%02X%02X%02X", ri, gi, bi) + case .AARRGGBB: return String(format: "#%02X%02X%02X%02X", ai, ri, gi, bi) + case .RRGGBBAA: return String(format: "#%02X%02X%02X%02X", ri, gi, bi, ai) } - - self = text } - - init(_ attributes: [StringWithAttributes]) { - self.init("") - for singleAttribute in attributes { - self = self + Text(singleAttribute) + + func hexString(_ digits: HexDigits) -> String { + switch digits { + case .d3: return hexString(.RGB) + case .d4: return hexString(.RGBA) + case .d6: return hexString(.RRGGBB) + case .d8: return hexString(.RRGGBBAA) } } - - init(_ attributedString: NSAttributedString) { - self.init(attributedString.stringsWithAttributes) +} + +// Source: https://swiftuirecipes.com/blog/swiftui-text-with-html-via-nsattributedstring +class HtmlString { + static func htmlToAttrStr(_ html: String, size: CGFloat, color: UIColor) -> NSAttributedString? { + let fullHTML = """ + <!doctype html> + <html> + <head> + <style> + body { + font-family: -apple-system; + font-size: \(size)px; + color: \(color.hexString(.RGB)) + } + </style> + </head> + <body> + \(html) + </body> + </html> + """ + if let data = fullHTML.data(using: .utf8) { + return try? NSAttributedString( + data: data, + options: [.documentType: NSAttributedString.DocumentType.html], + documentAttributes: nil) + } + return nil } } |