Implement mention rendering
This commit is contained in:
parent
cbc12977d3
commit
a1d40a5933
|
@ -676,12 +676,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
|
||||
shouldIgnoreEvents = outgoingMessage.messageState != TSOutgoingMessageStateSent;
|
||||
}
|
||||
NSString *threadID = self.viewItem.interaction.uniqueThreadId;
|
||||
[self.class loadForTextDisplay:self.bodyTextView
|
||||
displayableText:self.displayableBodyText
|
||||
searchText:self.delegate.lastSearchedText
|
||||
textColor:self.bodyTextColor
|
||||
font:self.textMessageFont
|
||||
shouldIgnoreEvents:shouldIgnoreEvents];
|
||||
shouldIgnoreEvents:shouldIgnoreEvents
|
||||
threadID:threadID];
|
||||
}
|
||||
|
||||
+ (void)loadForTextDisplay:(OWSMessageTextView *)textView
|
||||
|
@ -690,11 +692,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
textColor:(UIColor *)textColor
|
||||
font:(UIFont *)font
|
||||
shouldIgnoreEvents:(BOOL)shouldIgnoreEvents
|
||||
threadID:(NSString *)threadID
|
||||
{
|
||||
textView.hidden = NO;
|
||||
textView.textColor = textColor;
|
||||
|
||||
// Honor dynamic type in the message bodies.
|
||||
textView.font = font;
|
||||
textView.linkTextAttributes = @{
|
||||
NSForegroundColorAttributeName : textColor,
|
||||
|
@ -703,21 +705,43 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
textView.shouldIgnoreEvents = shouldIgnoreEvents;
|
||||
|
||||
NSString *text = displayableText.displayText;
|
||||
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]
|
||||
initWithString:text
|
||||
attributes:@{ NSFontAttributeName : font, NSForegroundColorAttributeName : textColor }];
|
||||
|
||||
NSError *error1;
|
||||
NSRegularExpression *regex1 = [[NSRegularExpression alloc] initWithPattern:@"@\\w*" options:0 error:&error1];
|
||||
OWSAssertDebug(error1 == nil);
|
||||
NSSet<NSString *> *knownUserIDs = LKAPI.userHexEncodedPublicKeyCache[threadID];
|
||||
NSMutableSet<NSValue *> *mentions = [NSMutableSet new];
|
||||
NSTextCheckingResult *match = [regex1 firstMatchInString:text options:NSMatchingWithoutAnchoringBounds range:NSMakeRange(0, text.length)];
|
||||
if (match != nil) {
|
||||
while (YES) {
|
||||
NSString *userID = [[text substringWithRange:match.range] stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""];
|
||||
NSUInteger matchEnd;
|
||||
if ([knownUserIDs containsObject:userID]) {
|
||||
NSString *userDisplayName = [Environment.shared.contactsManager attributedContactOrProfileNameForPhoneIdentifier:userID primaryFont:font secondaryFont:font].string;
|
||||
text = [text stringByReplacingCharactersInRange:match.range withString:[NSString stringWithFormat:@"@%@", userDisplayName]];
|
||||
[mentions addObject:[NSValue valueWithRange:NSMakeRange(match.range.location, userDisplayName.length + 1)]];
|
||||
matchEnd = match.range.location + userDisplayName.length;
|
||||
} else {
|
||||
matchEnd = match.range.location + match.range.length;
|
||||
}
|
||||
match = [regex1 firstMatchInString:text options:NSMatchingWithoutAnchoringBounds range:NSMakeRange(matchEnd, text.length - matchEnd)];
|
||||
if (match == nil) { break; }
|
||||
}
|
||||
}
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:@{ NSFontAttributeName : font, NSForegroundColorAttributeName : textColor }];
|
||||
for (NSValue *mention in mentions) {
|
||||
NSRange range = mention.rangeValue;
|
||||
[attributedText addAttribute:NSBackgroundColorAttributeName value:UIColor.lokiDarkGray range:range];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName value:UIColor.ows_whiteColor range:range];
|
||||
}
|
||||
|
||||
if (searchText.length >= ConversationSearchController.kMinimumSearchTextLength) {
|
||||
NSString *searchableText = [FullTextSearchFinder normalizeWithText:searchText];
|
||||
NSError *error;
|
||||
NSRegularExpression *regex =
|
||||
[[NSRegularExpression alloc] initWithPattern:[NSRegularExpression escapedPatternForString:searchableText]
|
||||
options:NSRegularExpressionCaseInsensitive
|
||||
error:&error];
|
||||
OWSAssertDebug(error == nil);
|
||||
NSError *error2;
|
||||
NSRegularExpression *regex2 = [[NSRegularExpression alloc] initWithPattern:[NSRegularExpression escapedPatternForString:searchableText] options:NSRegularExpressionCaseInsensitive error:&error2];
|
||||
OWSAssertDebug(error2 == nil);
|
||||
for (NSTextCheckingResult *match in
|
||||
[regex matchesInString:text options:NSMatchingWithoutAnchoringBounds range:NSMakeRange(0, text.length)]) {
|
||||
|
||||
[regex2 matchesInString:text options:NSMatchingWithoutAnchoringBounds range:NSMakeRange(0, text.length)]) {
|
||||
OWSAssertDebug(match.range.length >= ConversationSearchController.kMinimumSearchTextLength);
|
||||
[attributedText addAttribute:NSBackgroundColorAttributeName value:UIColor.yellowColor range:match.range];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName value:UIColor.ows_blackColor range:match.range];
|
||||
|
|
|
@ -260,7 +260,7 @@ public final class LokiAPI : NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: Caching
|
||||
// MARK: Message Caching
|
||||
private static let receivedMessageHashValuesKey = "receivedMessageHashValuesKey"
|
||||
private static let receivedMessageHashValuesCollection = "receivedMessageHashValuesCollection"
|
||||
|
||||
|
@ -293,6 +293,19 @@ public final class LokiAPI : NSObject {
|
|||
transaction.setObject(receivedMessageHashValues, forKey: receivedMessageHashValuesKey, inCollection: receivedMessageHashValuesCollection)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: User ID Caching
|
||||
@objc static var userHexEncodedPublicKeyCache: [String:Set<String>] = [:] // Thread ID to set of user hex encoded public keys
|
||||
|
||||
@objc public static func cache(_ userHexEncodedPublicKey: String, for thread: String) {
|
||||
if let cache = userHexEncodedPublicKeyCache[thread] {
|
||||
var mutableCache = cache
|
||||
mutableCache.insert(userHexEncodedPublicKey)
|
||||
userHexEncodedPublicKeyCache[thread] = mutableCache
|
||||
} else {
|
||||
userHexEncodedPublicKeyCache[thread] = [ userHexEncodedPublicKey ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Error Handling
|
||||
|
|
|
@ -1413,15 +1413,20 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return nil;
|
||||
}
|
||||
|
||||
// Loki: Cache the user hex encoded public key (for mentions)
|
||||
[LKAPI cache:incomingMessage.authorId for:oldGroupThread.uniqueId];
|
||||
|
||||
[self finalizeIncomingMessage:incomingMessage
|
||||
thread:oldGroupThread
|
||||
envelope:envelope
|
||||
transaction:transaction];
|
||||
|
||||
// Loki: Map the message ID to the message server ID if needed
|
||||
if (dataMessage.publicChatInfo != nil && dataMessage.publicChatInfo.hasServerID) {
|
||||
[self.primaryStorage setIDForMessageWithServerID:dataMessage.publicChatInfo.serverID to:incomingMessage.uniqueId in:transaction];
|
||||
}
|
||||
|
||||
// Loki: Generate a link preview if needed
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString *linkPreviewURL = [OWSLinkPreview previewURLForRawBodyText:incomingMessage.body];
|
||||
if (linkPreviewURL != nil) {
|
||||
|
|
Loading…
Reference in New Issue