Rename detectPermalinks to addMatrixEntityPermalinkAttributesTo and move code around

This commit is contained in:
Stefan Ceriu
2025-08-21 13:01:57 +03:00
committed by Doug
parent 84068fb926
commit 549a8de6a9
3 changed files with 45 additions and 19 deletions
@@ -11,14 +11,49 @@ import Foundation
import LRUCache import LRUCache
import MatrixRustSDK import MatrixRustSDK
protocol MentionBuilderProtocol {
func handleUserMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, userID: String, userDisplayName: String?)
func handleRoomIDMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, roomID: String)
func handleRoomAliasMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, roomAlias: String, roomDisplayName: String?)
func handleEventOnRoomAliasMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, eventID: String, roomAlias: String)
func handleEventOnRoomIDMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, eventID: String, roomID: String)
func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange)
}
struct AttributedStringBuilder: AttributedStringBuilderProtocol { struct AttributedStringBuilder: AttributedStringBuilderProtocol {
private static let defaultKey = "default"
private let builder: AttributedStringBuilderProtocol
static var useNextGenHTMLParser = false
static func invalidateCaches() {
AttributedStringBuilderV1.invalidateCaches()
}
init(cacheKey: String = defaultKey, mentionBuilder: MentionBuilderProtocol) {
builder = AttributedStringBuilderV1(cacheKey: cacheKey, mentionBuilder: mentionBuilder)
}
func fromPlain(_ string: String?) -> AttributedString? {
builder.fromPlain(string)
}
func fromHTML(_ htmlString: String?) -> AttributedString? {
builder.fromHTML(htmlString)
}
func addMatrixEntityPermalinkAttributesTo(_ attributedString: NSMutableAttributedString) {
builder.addMatrixEntityPermalinkAttributesTo(attributedString)
}
}
private struct AttributedStringBuilderV1: AttributedStringBuilderProtocol {
private let cacheKey: String private let cacheKey: String
private let temporaryBlockquoteMarkingColor = UIColor.magenta private let temporaryBlockquoteMarkingColor = UIColor.magenta
private let temporaryCodeBlockMarkingColor = UIColor.cyan private let temporaryCodeBlockMarkingColor = UIColor.cyan
private let mentionBuilder: MentionBuilderProtocol private let mentionBuilder: MentionBuilderProtocol
private static let defaultKey = "default"
private static let cacheDispatchQueue = DispatchQueue(label: "io.element.elementx.attributed_string_builder_cache") private static let cacheDispatchQueue = DispatchQueue(label: "io.element.elementx.attributed_string_builder_cache")
private static var caches: [String: LRUCache<String, AttributedString>] = [:] private static var caches: [String: LRUCache<String, AttributedString>] = [:]
@@ -26,7 +61,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
caches.removeAll() caches.removeAll()
} }
init(cacheKey: String = defaultKey, mentionBuilder: MentionBuilderProtocol) { init(cacheKey: String, mentionBuilder: MentionBuilderProtocol) {
self.cacheKey = cacheKey self.cacheKey = cacheKey
self.mentionBuilder = mentionBuilder self.mentionBuilder = mentionBuilder
} }
@@ -43,7 +78,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
let mutableAttributedString = NSMutableAttributedString(string: string) let mutableAttributedString = NSMutableAttributedString(string: string)
removeDefaultForegroundColors(mutableAttributedString) removeDefaultForegroundColors(mutableAttributedString)
addLinksAndMentions(mutableAttributedString) addLinksAndMentions(mutableAttributedString)
detectPermalinks(mutableAttributedString) addMatrixEntityPermalinkAttributesTo(mutableAttributedString)
let result = try? AttributedString(mutableAttributedString, including: \.elementX) let result = try? AttributedString(mutableAttributedString, including: \.elementX)
Self.cacheValue(result, forKey: string, cacheKey: cacheKey) Self.cacheValue(result, forKey: string, cacheKey: cacheKey)
@@ -102,7 +137,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
addLinksAndMentions(mutableAttributedString) addLinksAndMentions(mutableAttributedString)
replaceMarkedBlockquotes(mutableAttributedString) replaceMarkedBlockquotes(mutableAttributedString)
replaceMarkedCodeBlocks(mutableAttributedString) replaceMarkedCodeBlocks(mutableAttributedString)
detectPermalinks(mutableAttributedString) addMatrixEntityPermalinkAttributesTo(mutableAttributedString)
removeDTCoreTextArtifacts(mutableAttributedString) removeDTCoreTextArtifacts(mutableAttributedString)
let result = try? AttributedString(mutableAttributedString, including: \.elementX) let result = try? AttributedString(mutableAttributedString, including: \.elementX)
@@ -264,7 +299,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
} }
} }
func detectPermalinks(_ attributedString: NSMutableAttributedString) { func addMatrixEntityPermalinkAttributesTo(_ attributedString: NSMutableAttributedString) {
attributedString.enumerateAttribute(.link, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in attributedString.enumerateAttribute(.link, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in
if value != nil { if value != nil {
if let url = value as? URL, if let url = value as? URL,
@@ -360,7 +395,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
} }
} }
extension UIColor { private extension UIColor {
func toHexString() -> String { func toHexString() -> String {
var red: CGFloat = 0.0 var red: CGFloat = 0.0
var green: CGFloat = 0.0 var green: CGFloat = 0.0
@@ -388,15 +423,6 @@ extension NSAttributedString.Key {
static let MatrixAllUsersMention: NSAttributedString.Key = .init(rawValue: AllUsersMentionAttribute.name) static let MatrixAllUsersMention: NSAttributedString.Key = .init(rawValue: AllUsersMentionAttribute.name)
} }
protocol MentionBuilderProtocol {
func handleUserMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, userID: String, userDisplayName: String?)
func handleRoomIDMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, roomID: String)
func handleRoomAliasMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, roomAlias: String, roomDisplayName: String?)
func handleEventOnRoomAliasMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, eventID: String, roomAlias: String)
func handleEventOnRoomIDMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, eventID: String, roomID: String)
func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange)
}
private struct TextParsingMatch { private struct TextParsingMatch {
enum MatchType { enum MatchType {
case userID(identifier: String) case userID(identifier: String)
@@ -18,5 +18,5 @@ protocol AttributedStringBuilderProtocol {
func fromHTML(_ htmlString: String?) -> AttributedString? func fromHTML(_ htmlString: String?) -> AttributedString?
func detectPermalinks(_ attributedString: NSMutableAttributedString) func addMatrixEntityPermalinkAttributesTo(_ attributedString: NSMutableAttributedString)
} }
@@ -493,7 +493,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
attributedString = NSMutableAttributedString(string: string, attributes: [.link: URL(string: urlString) as Any]) attributedString = NSMutableAttributedString(string: string, attributes: [.link: URL(string: urlString) as Any])
} }
attributedStringBuilder.detectPermalinks(attributedString) attributedStringBuilder.addMatrixEntityPermalinkAttributesTo(attributedString)
// In RTE mentions don't need to be handled as links // In RTE mentions don't need to be handled as links
attributedString.removeAttribute(.link, range: NSRange(location: 0, length: attributedString.length)) attributedString.removeAttribute(.link, range: NSRange(location: 0, length: attributedString.length))
@@ -606,7 +606,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
attributedString.addAttribute(.MatrixAllUsersMention, value: true, range: match.range) attributedString.addAttribute(.MatrixAllUsersMention, value: true, range: match.range)
} }
attributedStringBuilder.detectPermalinks(attributedString) attributedStringBuilder.addMatrixEntityPermalinkAttributesTo(attributedString)
state.bindings.plainComposerText = attributedString state.bindings.plainComposerText = attributedString
} }