Improve performance when displaying posts with many custom emojis

Closes #204
This commit is contained in:
Shadowfacts 2022-11-05 11:00:14 -04:00
parent b9555cf7dd
commit 97a95c435e
2 changed files with 22 additions and 21 deletions

View File

@ -22,8 +22,7 @@ extension NSTextAttachment {
image.draw(in: CGRect(origin: .zero, size: imageSizeMatchingFontSize)) image.draw(in: CGRect(origin: .zero, size: imageSizeMatchingFontSize))
} }
self.init() self.init(image: attachmentImage)
self.image = attachmentImage
} }
convenience init(emojiPlaceholderIn font: UIFont) { convenience init(emojiPlaceholderIn font: UIFont) {
@ -31,7 +30,6 @@ extension NSTextAttachment {
// assumes emoji are mostly square // assumes emoji are mostly square
let size = CGSize(width: adjustedCapHeight, height: adjustedCapHeight) let size = CGSize(width: adjustedCapHeight, height: adjustedCapHeight)
let image = UIGraphicsImageRenderer(size: size).image { (_) in } let image = UIGraphicsImageRenderer(size: size).image { (_) in }
self.init() self.init(image: image)
self.image = image
} }
} }

View File

@ -86,28 +86,31 @@ extension BaseEmojiLabel {
func buildStringWithEmojisReplaced(usePlaceholders: Bool) -> NSAttributedString { func buildStringWithEmojisReplaced(usePlaceholders: Bool) -> NSAttributedString {
let mutAttrString = NSMutableAttributedString(attributedString: attributedString) let mutAttrString = NSMutableAttributedString(attributedString: attributedString)
// lock once for the entire loop, rather than lock/unlocking for each iteration to do the lookup
// OSAllocatedUnfairLock.withLock expects a @Sendable closure, so this warns about captures of non-sendable types (attribute dstrings, text checking results) // OSAllocatedUnfairLock.withLock expects a @Sendable closure, so this warns about captures of non-sendable types (attribute dstrings, text checking results)
// even though the closures is invoked on the same thread that withLock is called, so it's unclear why it needs to be @Sendable (FB11494878) // even though the closures is invoked on the same thread that withLock is called, so it's unclear why it needs to be @Sendable (FB11494878)
// so, just ignore the warnings // so, just ignore the warnings
emojiImages.withLock { emojiImages in let emojiAttachments = emojiImages.withLock {
// replaces the emojis starting from the end of the string as to not alter the indices of preceeding emojis $0.mapValues { image in
for match in matches.reversed() { NSTextAttachment(emojiImage: image, in: self.emojiFont, with: self.emojiTextColor)
let shortcode = (attributedString.string as NSString).substring(with: match.range(at: 1))
let attachment: NSTextAttachment
if let emojiImage = emojiImages[shortcode] {
attachment = NSTextAttachment(emojiImage: emojiImage, in: self.emojiFont, with: self.emojiTextColor)
} else if usePlaceholders {
attachment = NSTextAttachment(emojiPlaceholderIn: self.emojiFont)
} else {
continue
}
let attachmentStr = NSAttributedString(attachment: attachment)
mutAttrString.replaceCharacters(in: match.range, with: attachmentStr)
} }
} }
let placeholder = usePlaceholders ? NSTextAttachment(emojiPlaceholderIn: self.emojiFont) : nil
// replaces the emojis starting from the end of the string as to not alter the indices of preceeding emojis
for match in matches.reversed() {
let shortcode = (attributedString.string as NSString).substring(with: match.range(at: 1))
let attachment: NSTextAttachment
if let emoji = emojiAttachments[shortcode] {
attachment = emoji
} else if usePlaceholders {
attachment = placeholder!
} else {
continue
}
let attachmentStr = NSAttributedString(attachment: attachment)
mutAttrString.replaceCharacters(in: match.range, with: attachmentStr)
}
return mutAttrString return mutAttrString
} }