mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Add permalink detection and custom attributed string attributes (#536)
* Pass full attributed string to TimelineItems and let the UI level handle blockquote coalescing * Add permalink detection and attribute embedding within the attributed string
This commit is contained in:
@@ -253,7 +253,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(attributedString.runs.count, 1)
|
||||
|
||||
XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 1)
|
||||
XCTAssertEqual(attributedString.formattedComponents.count, 1)
|
||||
|
||||
for run in attributedString.runs where run.elementX.blockquote ?? false {
|
||||
return
|
||||
@@ -277,7 +277,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(attributedString.runs.count, 3)
|
||||
|
||||
XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 3)
|
||||
XCTAssertEqual(attributedString.formattedComponents.count, 3)
|
||||
|
||||
for run in attributedString.runs where run.elementX.blockquote ?? false {
|
||||
return
|
||||
@@ -298,10 +298,8 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(attributedString.runs.count, 3)
|
||||
|
||||
guard let coalescedComponents = attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString) else {
|
||||
XCTFail("Could not build the attributed string components")
|
||||
return
|
||||
}
|
||||
let coalescedComponents = attributedString.formattedComponents
|
||||
|
||||
XCTAssertEqual(coalescedComponents.count, 1)
|
||||
|
||||
XCTAssertEqual(coalescedComponents.first?.attributedString.runs.count, 3, "Link not present in the component")
|
||||
@@ -322,10 +320,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
return
|
||||
}
|
||||
|
||||
guard let coalescedComponents = attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString) else {
|
||||
XCTFail("Could not build the attributed string components")
|
||||
return
|
||||
}
|
||||
let coalescedComponents = attributedString.formattedComponents
|
||||
XCTAssertEqual(coalescedComponents.count, 1)
|
||||
|
||||
guard let component = coalescedComponents.first else {
|
||||
@@ -351,7 +346,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(attributedString.runs.count, 7)
|
||||
|
||||
XCTAssertEqual(attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString)?.count, 1)
|
||||
XCTAssertEqual(attributedString.formattedComponents.count, 1)
|
||||
|
||||
var numberOfBlockquotes = 0
|
||||
for run in attributedString.runs where run.elementX.blockquote ?? false && run.link != nil {
|
||||
@@ -378,10 +373,7 @@ class AttributedStringBuilderTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(attributedString.runs.count, 12)
|
||||
|
||||
guard let coalescedComponents = attributedStringBuilder.blockquoteCoalescedComponentsFrom(attributedString) else {
|
||||
XCTFail("Could not build the attributed string components")
|
||||
return
|
||||
}
|
||||
let coalescedComponents = attributedString.formattedComponents
|
||||
|
||||
XCTAssertEqual(coalescedComponents.count, 6)
|
||||
for component in coalescedComponents where component.isReply {
|
||||
|
||||
@@ -210,30 +210,24 @@ class LoggingTests: XCTestCase {
|
||||
func testTimelineContentIsRedacted() throws {
|
||||
// Given timeline items that contain text
|
||||
let textAttributedString = "TextAttributed"
|
||||
let textMessage = TextRoomTimelineItem(id: "mytextmessage", text: "TextString",
|
||||
attributedComponents: [.init(attributedString: AttributedString(textAttributedString),
|
||||
isBlockquote: false,
|
||||
isReply: false)],
|
||||
let textMessage = TextRoomTimelineItem(id: "mytextmessage", body: "TextString",
|
||||
formattedBody: AttributedString(textAttributedString),
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false, sender: .init(id: "sender"))
|
||||
let noticeAttributedString = "NoticeAttributed"
|
||||
let noticeMessage = NoticeRoomTimelineItem(id: "mynoticemessage", text: "NoticeString",
|
||||
attributedComponents: [.init(attributedString: AttributedString(noticeAttributedString),
|
||||
isBlockquote: false,
|
||||
isReply: false)],
|
||||
let noticeMessage = NoticeRoomTimelineItem(id: "mynoticemessage", body: "NoticeString",
|
||||
formattedBody: AttributedString(noticeAttributedString),
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false, sender: .init(id: "sender"))
|
||||
let emoteAttributedString = "EmoteAttributed"
|
||||
let emoteMessage = EmoteRoomTimelineItem(id: "myemotemessage", text: "EmoteString",
|
||||
attributedComponents: [.init(attributedString: AttributedString(emoteAttributedString),
|
||||
isBlockquote: false,
|
||||
isReply: false)],
|
||||
let emoteMessage = EmoteRoomTimelineItem(id: "myemotemessage", body: "EmoteString",
|
||||
formattedBody: AttributedString(emoteAttributedString),
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false, sender: .init(id: "sender"))
|
||||
let imageMessage = ImageRoomTimelineItem(id: "myimagemessage", text: "ImageString",
|
||||
let imageMessage = ImageRoomTimelineItem(id: "myimagemessage", body: "ImageString",
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false,
|
||||
sender: .init(id: "sender"), source: nil)
|
||||
let videoMessage = VideoRoomTimelineItem(id: "myvideomessage", text: "VideoString",
|
||||
let videoMessage = VideoRoomTimelineItem(id: "myvideomessage", body: "VideoString",
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false,
|
||||
sender: .init(id: "sender"), duration: 0, source: nil, thumbnailSource: nil)
|
||||
let fileMessage = FileRoomTimelineItem(id: "myfilemessage", text: "FileString",
|
||||
let fileMessage = FileRoomTimelineItem(id: "myfilemessage", body: "FileString",
|
||||
timestamp: "", groupState: .single, isOutgoing: false, isEditable: false,
|
||||
sender: .init(id: "sender"), source: nil, thumbnailSource: nil)
|
||||
|
||||
@@ -258,25 +252,25 @@ class LoggingTests: XCTestCase {
|
||||
|
||||
let content = try String(contentsOf: logFile)
|
||||
XCTAssertTrue(content.contains(textMessage.id))
|
||||
XCTAssertFalse(content.contains(textMessage.text))
|
||||
XCTAssertFalse(content.contains(textMessage.body))
|
||||
XCTAssertFalse(content.contains(textAttributedString))
|
||||
|
||||
XCTAssertTrue(content.contains(noticeMessage.id))
|
||||
XCTAssertFalse(content.contains(noticeMessage.text))
|
||||
XCTAssertFalse(content.contains(noticeMessage.body))
|
||||
XCTAssertFalse(content.contains(noticeAttributedString))
|
||||
|
||||
XCTAssertTrue(content.contains(emoteMessage.id))
|
||||
XCTAssertFalse(content.contains(emoteMessage.text))
|
||||
XCTAssertFalse(content.contains(emoteMessage.body))
|
||||
XCTAssertFalse(content.contains(emoteAttributedString))
|
||||
|
||||
XCTAssertTrue(content.contains(imageMessage.id))
|
||||
XCTAssertFalse(content.contains(imageMessage.text))
|
||||
XCTAssertFalse(content.contains(imageMessage.body))
|
||||
|
||||
XCTAssertTrue(content.contains(videoMessage.id))
|
||||
XCTAssertFalse(content.contains(videoMessage.text))
|
||||
XCTAssertFalse(content.contains(videoMessage.body))
|
||||
|
||||
XCTAssertTrue(content.contains(fileMessage.id))
|
||||
XCTAssertFalse(content.contains(fileMessage.text))
|
||||
XCTAssertFalse(content.contains(fileMessage.body))
|
||||
}
|
||||
|
||||
func testRustMessageContentIsRedacted() throws {
|
||||
|
||||
@@ -106,4 +106,21 @@ class PermalinkBuilderTests: XCTestCase {
|
||||
XCTAssertEqual(error as? PermalinkBuilderError, PermalinkBuilderError.invalidEventIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
func testPermalinkDetection() {
|
||||
var url = URL(staticString: "https://www.matrix.org")
|
||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url), nil)
|
||||
|
||||
url = URL(staticString: "https://matrix.to/#/@bob:matrix.org?via=matrix.org")
|
||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url), PermalinkType.userIdentifier("@bob:matrix.org"))
|
||||
|
||||
url = URL(staticString: "https://matrix.to/#/!roomidentifier:matrix.org?via=matrix.org")
|
||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url), PermalinkType.roomIdentifier("!roomidentifier:matrix.org"))
|
||||
|
||||
url = URL(staticString: "https://matrix.to/#/%23roomalias:matrix.org?via=matrix.org")
|
||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url), PermalinkType.roomAlias("#roomalias:matrix.org"))
|
||||
|
||||
url = URL(staticString: "https://matrix.to/#/!roomidentifier:matrix.org/$eventidentifier?via=matrix.org")
|
||||
XCTAssertEqual(PermalinkBuilder.detectPermalink(in: url), PermalinkType.event(roomIdentifier: "!roomidentifier:matrix.org", eventIdentifier: "$eventidentifier"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user