@ -429,10 +429,14 @@ public class OWSLinkPreview: MTLModel {
// MARK: - T e x t P a r s i n g
// T h i s c a c h e s h o u l d o n l y b e a c c e s s e d o n m a i n t h r e a d .
private static var previewUrlCache : NSCache < AnyObject , AnyObject > = NSCache ( )
private static var previewUrlCache : NSCache < NSString , NSString > = NSCache ( )
@objc
public class func previewUrl ( forMessageBodyText body : String ? ) -> String ? {
public class func previewUrl ( forRawBodyText body : String ? , selectedRange : NSRange ) -> String ? {
return previewUrl ( forMessageBodyText : body , selectedRange : selectedRange )
}
public class func previewUrl ( forMessageBodyText body : String ? , selectedRange : NSRange ? ) -> String ? {
AssertIsOnMainThread ( )
// E x i t e a r l y i f l i n k p r e v i e w s a r e n o t e n a b l e d i n o r d e r t o a v o i d
@ -440,38 +444,62 @@ public class OWSLinkPreview: MTLModel {
guard OWSLinkPreview . featureEnabled else {
return nil
}
guard SSKPreferences . areLinkPreviewsEnabled ( ) else {
return nil
}
if let cachedUrl = previewUrlCache . object ( forKey : body as AnyObject ) as ? String {
guard let body = body else {
return nil
}
if let cachedUrl = previewUrlCache . object ( forKey : body as NSString ) as String ? {
Logger . verbose ( " URL parsing cache hit. " )
guard cachedUrl . count > 0 else {
return nil
}
return cachedUrl
}
let previewUrl s = allPreviewUrl s( forMessageBodyText : body )
guard let previewUrl = previewUrl s. first else {
let previewUrl Matche s = allPreviewUrl Matche s( forMessageBodyText : body )
guard let urlMatch = previewUrlMatche s. first else {
// U s e e m p t y s t r i n g t o i n d i c a t e " n o p r e v i e w U R L " i n t h e c a c h e .
previewUrlCache . setObject ( " " as AnyObject , forKey : body as AnyObject )
previewUrlCache . setObject ( " " , forKey : body as NSString )
return nil
}
previewUrlCache . setObject ( previewUrl as AnyObject , forKey : body as AnyObject )
return previewUrl
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 || cursorAtEndOfMatch ) {
Logger . debug ( " ignoring URL, since the user is currently editing it. " )
// w e d o n ' t w a n t t o c a c h e t h e r e s u l t h e r e , a s w e w a n t t o f e t c h t h e l i n k p r e v i e w
// i f t h e u s e r m o v e s t h e c u r s o r .
return nil
}
Logger . debug ( " considering URL, since the user is not currently editing it. " )
}
previewUrlCache . setObject ( urlMatch . urlString as NSString , forKey : body as NSString )
return urlMatch . urlString
}
class func allPreviewUrls ( forMessageBodyText body : String ? ) -> [ String ] {
struct URLMatchResult {
let urlString : String
let matchRange : NSRange
}
class func allPreviewUrls ( forMessageBodyText body : String ) -> [ String ] {
return allPreviewUrlMatches ( forMessageBodyText : body ) . map { $0 . urlString }
}
class func allPreviewUrlMatches ( forMessageBodyText body : String ) -> [ URLMatchResult ] {
guard OWSLinkPreview . featureEnabled else {
return [ ]
}
guard SSKPreferences . areLinkPreviewsEnabled ( ) else {
return [ ]
}
guard let body = body else {
return [ ]
}
let detector : NSDataDetector
do {
@ -481,7 +509,7 @@ public class OWSLinkPreview: MTLModel {
return [ ]
}
var previewUrls = [ String ] ( )
var urlMatches: [ URLMatchResult ] = [ ]
let matches = detector . matches ( in : body , options : [ ] , range : NSRange ( location : 0 , length : body . count ) )
for match in matches {
guard let matchURL = match . url else {
@ -490,21 +518,22 @@ public class OWSLinkPreview: MTLModel {
}
let urlString = matchURL . absoluteString
if isValidLinkUrl ( urlString ) {
previewUrls . append ( urlString )
let matchResult = URLMatchResult ( urlString : urlString , matchRange : match . range )
urlMatches . append ( matchResult )
}
}
return previewUrl s
return urlMatche s
}
// MARK: - P r e v i e w C o n s t r u c t i o n
// T h i s c a c h e s h o u l d o n l y b e a c c e s s e d o n s e r i a l Q u e u e .
private static var linkPreviewDraftCache : NSCache < AnyObject , OWSLinkPreviewDraft > = NSCache ( )
private static var linkPreviewDraftCache : NSCache < NSString , OWSLinkPreviewDraft > = NSCache ( )
private class func cachedLinkPreview ( forPreviewUrl previewUrl : String ) -> OWSLinkPreviewDraft ? {
var result : OWSLinkPreviewDraft ?
serialQueue . sync {
result = linkPreviewDraftCache . object ( forKey : previewUrl as AnyObject )
result = linkPreviewDraftCache . object ( forKey : previewUrl as NSString )
}
return result
}
@ -522,7 +551,7 @@ public class OWSLinkPreview: MTLModel {
}
serialQueue . sync {
previewUrl Cache. setObject ( linkPreviewDraft , forKey : previewUrl as AnyObject )
linkPreviewDraft Cache. setObject ( linkPreviewDraft , forKey : previewUrl as NSString )
}
}