mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Pill View (#1797)
* provider can now check the current session * More testable code * created the test condition * it works but not always not sure why, need to dig deeper * sadly we need to use textkit 1 to solve this issue * removed developer option screen test * this experimental solution kinda works but I need a way to pill recomputation is weird * format * display improvement * better and faster solution * pilished the code * better coloring * swift format * just need to solve the caching issue * fix caching issue * tests done! * changelog * pr comments addressed * all pr comments addressed * docs * line lenght * updated tests and fixed a parsing permalink issue * MentionBuilder * pr comments * swiftformat * code blocks should not have links * Update ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/Services/Client/ClientProxy.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update UnitTests/Sources/AttributedStringBuilderTests.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/UITests/UITestsAppCoordinator.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/Other/Pills/PillAttachmentViewProvider.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * Update ElementX/Sources/Other/Pills/MentionBuilder.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * pr comments * swiftformat --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>
This commit is contained in:
@@ -15,21 +15,49 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
final class MessageTextView: UITextView {
|
||||
var roomContext: RoomScreenViewModel.Context?
|
||||
var updateClosure: (() -> Void)?
|
||||
|
||||
// This prevents the magnifying glass from showing up
|
||||
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
gestureRecognizer as? UILongPressGestureRecognizer == nil
|
||||
}
|
||||
|
||||
func invalidateTextAttachmentsDisplay(update: Bool) {
|
||||
attributedText.enumerateAttribute(.attachment,
|
||||
in: NSRange(location: 0, length: attributedText.length),
|
||||
options: []) { value, range, _ in
|
||||
guard value != nil else {
|
||||
return
|
||||
}
|
||||
self.layoutManager.invalidateDisplay(forCharacterRange: range)
|
||||
if update {
|
||||
updateClosure?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Required to setup the first rendering of the pill view
|
||||
override func layoutSubviews() {
|
||||
invalidateTextAttachmentsDisplay(update: false)
|
||||
super.layoutSubviews()
|
||||
}
|
||||
}
|
||||
|
||||
struct MessageText: UIViewRepresentable {
|
||||
@Environment(\.openURL) private var openURLAction: OpenURLAction
|
||||
let attributedString: AttributedString
|
||||
@EnvironmentObject private var viewModel: RoomScreenViewModel.Context
|
||||
@State var attributedString: AttributedString
|
||||
|
||||
func makeUIView(context: Context) -> MessageTextView {
|
||||
let textView = MessageTextView()
|
||||
// Need to use TextKit 1 for mentions
|
||||
let textView = MessageTextView(usingTextLayoutManager: false)
|
||||
textView.roomContext = viewModel
|
||||
textView.updateClosure = {
|
||||
attributedString = AttributedString(textView.attributedText)
|
||||
}
|
||||
textView.isEditable = false
|
||||
textView.isScrollEnabled = false
|
||||
textView.adjustsFontForContentSizeCategory = true
|
||||
@@ -46,7 +74,7 @@ struct MessageText: UIViewRepresentable {
|
||||
textView.contentInsetAdjustmentBehavior = .never
|
||||
textView.textContainerInset = .zero
|
||||
textView.textContainer.lineFragmentPadding = 0
|
||||
textView.textLayoutManager?.usesFontLeading = false
|
||||
textView.layoutManager.usesFontLeading = false
|
||||
textView.backgroundColor = .clear
|
||||
textView.attributedText = NSAttributedString(attributedString)
|
||||
textView.delegate = context.coordinator
|
||||
@@ -94,9 +122,20 @@ struct MessageText_Previews: PreviewProvider, TestablePreview {
|
||||
container.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
return container
|
||||
}()
|
||||
|
||||
|
||||
private static let attributedString = AttributedString("Hello World! Hello world! Hello world! Hello world! Hello World! Hellooooooooooooooooooooooo Woooooooooooooooooooooorld", attributes: defaultFontContainer)
|
||||
private static let attributedStringWithAttachment = "Hello " + AttributedString(NSAttributedString(attachment: PillTextAttachment(data: Data(), ofType: InfoPlistReader.main.pillsUTType))) + " World!"
|
||||
|
||||
private static let attributedStringWithAttachment: AttributedString = {
|
||||
let testData = PillTextAttachmentData(type: .user(userID: "@alice:example.com"), font: .preferredFont(forTextStyle: .body))
|
||||
guard let attachment = PillTextAttachment(attachmentData: testData) else {
|
||||
return AttributedString()
|
||||
}
|
||||
|
||||
var attributedString = "Hello test test test " + AttributedString(NSAttributedString(attachment: attachment)) + " World!"
|
||||
attributedString
|
||||
.mergeAttributes(defaultFontContainer)
|
||||
return attributedString
|
||||
}()
|
||||
|
||||
private static let htmlStringWithQuote =
|
||||
"""
|
||||
@@ -106,28 +145,36 @@ struct MessageText_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
private static let htmlStringWithList = "<p>This is a list</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n<li>And number 3</li>\n</ul>\n"
|
||||
|
||||
private static let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL)
|
||||
private static let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true))
|
||||
|
||||
static var attachmentPreview: some View {
|
||||
MessageText(attributedString: attributedStringWithAttachment)
|
||||
.border(Color.purple)
|
||||
.environmentObject(RoomScreenViewModel.mock.context)
|
||||
}
|
||||
|
||||
static var previews: some View {
|
||||
MessageText(attributedString: attributedString)
|
||||
.border(Color.purple)
|
||||
.previewDisplayName("Custom Text")
|
||||
.environmentObject(RoomScreenViewModel.mock.context)
|
||||
// For comparison
|
||||
Text(attributedString)
|
||||
.border(Color.purple)
|
||||
.previewDisplayName("SwiftUI Default Text")
|
||||
MessageText(attributedString: attributedStringWithAttachment)
|
||||
.border(Color.purple)
|
||||
attachmentPreview
|
||||
.previewDisplayName("Custom Attachment")
|
||||
if let attributedString = attributedStringBuilder.fromHTML(htmlStringWithQuote) {
|
||||
MessageText(attributedString: attributedString)
|
||||
.border(Color.purple)
|
||||
.previewDisplayName("With block quote")
|
||||
.environmentObject(RoomScreenViewModel.mock.context)
|
||||
}
|
||||
if let attributedString = attributedStringBuilder.fromHTML(htmlStringWithList) {
|
||||
MessageText(attributedString: attributedString)
|
||||
.border(Color.purple)
|
||||
.previewDisplayName("With list")
|
||||
.environmentObject(RoomScreenViewModel.mock.context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user