diff --git a/ElementX/Sources/Other/Pills/MessageText.swift b/ElementX/Sources/Other/Pills/MessageText.swift index 5433def53..0fbb7e4ae 100644 --- a/ElementX/Sources/Other/Pills/MessageText.swift +++ b/ElementX/Sources/Other/Pills/MessageText.swift @@ -26,7 +26,7 @@ final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate { gestureRecognizer as? UILongPressGestureRecognizer == nil } - func invalidateTextAttachmentsDisplay(update: Bool) { + func invalidateTextAttachmentsDisplay() { attributedText.enumerateAttribute(.attachment, in: NSRange(location: 0, length: attributedText.length), options: []) { value, range, _ in @@ -34,9 +34,7 @@ final class MessageTextView: UITextView, PillAttachmentViewProviderDelegate { return } self.layoutManager.invalidateDisplay(forCharacterRange: range) - if update { - updateClosure?() - } + updateClosure?() } } diff --git a/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift b/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift index d01366e51..40c174a33 100644 --- a/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift +++ b/ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift @@ -24,7 +24,7 @@ protocol PillAttachmentViewProviderDelegate: AnyObject { var roomContext: RoomScreenViewModel.Context? { get } func registerPillView(_ pillView: UIView) - func invalidateTextAttachmentsDisplay(update: Bool) + func invalidateTextAttachmentsDisplay() } final class PillAttachmentViewProvider: NSTextAttachmentViewProvider { @@ -44,7 +44,8 @@ final class PillAttachmentViewProvider: NSTextAttachmentViewProvider { override func loadView() { super.loadView() - guard let textAttachmentData = (textAttachment as? PillTextAttachment)?.pillData else { + guard let textAttachment = textAttachment as? PillTextAttachment, + let pillData = textAttachment.pillData else { MXLog.failure("[PillAttachmentViewProvider]: attachment is missing data or not of expected class") return } @@ -56,15 +57,16 @@ final class PillAttachmentViewProvider: NSTextAttachmentViewProvider { context = PillContext.mock(type: .loadUser(isOwn: false)) imageProvider = MockMediaProvider() } else if let roomContext = delegate?.roomContext { - context = PillContext(roomContext: roomContext, data: textAttachmentData) + context = PillContext(roomContext: roomContext, data: pillData) imageProvider = roomContext.imageProvider } else { MXLog.failure("[PillAttachmentViewProvider]: missing room context") return } - let view = PillView(imageProvider: imageProvider, context: context) { [weak self] in - self?.delegate?.invalidateTextAttachmentsDisplay(update: true) + let view = PillView(imageProvider: imageProvider, context: context) { [weak self, weak textAttachment] in + textAttachment?.invalidateLastBounds() + self?.delegate?.invalidateTextAttachmentsDisplay() } let controller = UIHostingController(rootView: view) controller.view.backgroundColor = .clear @@ -93,5 +95,5 @@ extension WysiwygTextView: PillAttachmentViewProviderDelegate { (mentionDisplayHelper as? ComposerMentionDisplayHelper)?.roomContext } - func invalidateTextAttachmentsDisplay(update: Bool) { } + func invalidateTextAttachmentsDisplay() { } } diff --git a/ElementX/Sources/Other/Pills/PillTextAttachment.swift b/ElementX/Sources/Other/Pills/PillTextAttachment.swift index 666172439..a294e1919 100644 --- a/ElementX/Sources/Other/Pills/PillTextAttachment.swift +++ b/ElementX/Sources/Other/Pills/PillTextAttachment.swift @@ -26,13 +26,22 @@ final class PillTextAttachment: NSTextAttachment { } private(set) var pillData: PillTextAttachmentData! + private var lastBounds: CGRect? + + func invalidateLastBounds() { + lastBounds = nil + } override func attachmentBounds(for textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect { + if let lastBounds { + return lastBounds + } var rect = super.attachmentBounds(for: textContainer, proposedLineFragment: lineFrag, glyphPosition: position, characterIndex: charIndex) let fontData = pillData.fontData // Align the pill text vertically with the surrounding text. rect.origin.y = fontData.descender + (fontData.lineHeight - rect.height) / 2.0 + lastBounds = rect return rect } }