diff --git a/Signal/test/util/ProtoParsingTest.m b/Signal/test/util/ProtoParsingTest.m index 6bb0e75d0..6e06aebbc 100644 --- a/Signal/test/util/ProtoParsingTest.m +++ b/Signal/test/util/ProtoParsingTest.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "SignalBaseTest.h" @@ -63,6 +63,10 @@ NS_ASSUME_NONNULL_BEGIN return nil; } +- (nonnull NSString *)displayNameForPhoneIdentifier:(NSString * _Nullable)recipientId transaction:(nonnull YapDatabaseReadTransaction *)transaction { + return nil; +} + @end #pragma mark - diff --git a/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift b/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift index 7483b7fd6..5663017dd 100644 --- a/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift +++ b/SignalServiceKit/src/Messages/Interactions/OWSLinkPreview.swift @@ -469,8 +469,9 @@ public class OWSLinkPreview: MTLModel { if let selectedRange = selectedRange { Logger.verbose("match: urlString: \(urlMatch.urlString) range: \(urlMatch.matchRange) selectedRange: \(selectedRange)") + let cursorAtEndOfMatch = urlMatch.matchRange.location + urlMatch.matchRange.length == selectedRange.location if selectedRange.location != body.count, - urlMatch.matchRange.intersection(selectedRange) != nil { + (urlMatch.matchRange.intersection(selectedRange) != nil || cursorAtEndOfMatch) { Logger.debug("ignoring URL, since the user is currently editing it.") // we don't want to cache the result here, as we want to fetch the link preview // if the user moves the cursor. diff --git a/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift b/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift index db5a1743c..41ec45fe2 100644 --- a/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift +++ b/SignalServiceKit/tests/Messages/OWSLinkPreviewTest.swift @@ -169,19 +169,20 @@ class OWSLinkPreviewTest: SSKBaseTestSwift { } func testPreviewUrlForMessageBodyText() { - XCTAssertNil(OWSLinkPreview.previewUrl(forMessageBodyText: "")) - XCTAssertNil(OWSLinkPreview.previewUrl(forMessageBodyText: "alice bob jim")) - XCTAssertNil(OWSLinkPreview.previewUrl(forMessageBodyText: "alice bob jim http://")) - XCTAssertNil(OWSLinkPreview.previewUrl(forMessageBodyText: "alice bob jim http://a.com")) + Assert(bodyText: "", extractsLink: nil) + Assert(bodyText: "alice bob jim", extractsLink: nil) + Assert(bodyText: "alice bob jim http://", extractsLink: nil) + Assert(bodyText: "alice bob jim http://a.com", extractsLink: nil) - XCTAssertEqual(OWSLinkPreview.previewUrl(forMessageBodyText: "https://www.youtube.com/watch?v=tP-Ipsat90c"), - "https://www.youtube.com/watch?v=tP-Ipsat90c") - XCTAssertEqual(OWSLinkPreview.previewUrl(forMessageBodyText: "alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim"), - "https://www.youtube.com/watch?v=tP-Ipsat90c") + Assert(bodyText: "https://www.youtube.com/watch?v=tP-Ipsat90c", + extractsLink: "https://www.youtube.com/watch?v=tP-Ipsat90c") + + Assert(bodyText: "alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim", + extractsLink: "https://www.youtube.com/watch?v=tP-Ipsat90c") // If there are more than one, take the first. - XCTAssertEqual(OWSLinkPreview.previewUrl(forMessageBodyText: "alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim https://www.youtube.com/watch?v=other-url carol"), - "https://www.youtube.com/watch?v=tP-Ipsat90c") + Assert(bodyText: "alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim https://www.youtube.com/watch?v=other-url carol", + extractsLink: "https://www.youtube.com/watch?v=tP-Ipsat90c") } func testUtils() { @@ -454,4 +455,87 @@ class OWSLinkPreviewTest: SSKBaseTestSwift { options: [], range: NSRange(location: 0, length: text.utf16.count))) } + + func testCursorPositions() { + // sanity check + Assert(bodyText: "https://www.youtube.com/watch?v=testCursorPositionsa", + extractsLink: "https://www.youtube.com/watch?v=testCursorPositionsa", + selectedRange: nil) + + // Don't extract link if cursor is touching text + let text2 = "https://www.youtube.com/watch?v=testCursorPositionsb" + XCTAssertEqual(text2.count, 52) + Assert(bodyText: text2, + extractsLink: nil, + selectedRange: NSRange(location: 51, length: 0)) + + Assert(bodyText: text2, + extractsLink: nil, + selectedRange: NSRange(location: 51, length: 10)) + + Assert(bodyText: text2, + extractsLink: nil, + selectedRange: NSRange(location: 0, length: 0)) + + // Unless the cursor is at the end of the text + Assert(bodyText: text2, + extractsLink: "https://www.youtube.com/watch?v=testCursorPositionsb", + selectedRange: NSRange(location: 52, length: 0)) + + // Once extracted, keep the existing link preview, even if the cursor moves back. + Assert(bodyText: text2, + extractsLink: "https://www.youtube.com/watch?v=testCursorPositionsb", + selectedRange: NSRange(location: 51, length: 0)) + + let text3 = "foo https://www.youtube.com/watch?v=testCursorPositionsc bar" + XCTAssertEqual(text3.count, 60) + + // front edge + Assert(bodyText: text3, + extractsLink: nil, + selectedRange: NSRange(location: 4, length: 0)) + + // middle + Assert(bodyText: text3, + extractsLink: nil, + selectedRange: NSRange(location: 4, length: 0)) + + // rear edge + Assert(bodyText: text3, + extractsLink: nil, + selectedRange: NSRange(location: 56, length: 0)) + + // extract link if selecting after link + Assert(bodyText: text3, + extractsLink: "https://www.youtube.com/watch?v=testCursorPositionsc", + selectedRange: NSRange(location: 57, length: 0)) + + let text4 = "bar https://www.youtube.com/watch?v=testCursorPositionsd foo" + XCTAssertEqual(text4.count, 60) + + // front edge + Assert(bodyText: text4, + extractsLink: nil, + selectedRange: NSRange(location: 4, length: 0)) + + // middle + Assert(bodyText: text4, + extractsLink: nil, + selectedRange: NSRange(location: 20, length: 0)) + + // rear edge + Assert(bodyText: text4, + extractsLink: nil, + selectedRange: NSRange(location: 56, length: 0)) + + // extract link if selecting before link + Assert(bodyText: text4, + extractsLink: "https://www.youtube.com/watch?v=testCursorPositionsd", + selectedRange: NSRange(location: 3, length: 0)) + } + + private func Assert(bodyText: String, extractsLink link: String?, selectedRange: NSRange? = nil, file: StaticString = #file, line: UInt = #line) { + let actual = OWSLinkPreview.previewUrl(forMessageBodyText: bodyText, selectedRange: selectedRange) + XCTAssertEqual(actual, link, file: file, line: line) + } }