Mention by display name rather than hex encoded public key

pull/59/head
Niels Andriesse 5 years ago
parent 966748ed1b
commit 2f39cd45f3

@ -567,6 +567,7 @@
B82584A02315024B001B41CB /* RSSFeedPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = B825849F2315024B001B41CB /* RSSFeedPoller.swift */; };
B845B4D4230CD09100D759F0 /* GroupChatPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = B845B4D3230CD09000D759F0 /* GroupChatPoller.swift */; };
B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; };
B84664F3234FE4540083A1CD /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84664F2234FE4530083A1CD /* Mention.swift */; };
B86BD08123399883000F5AE3 /* QRCodeModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08023399883000F5AE3 /* QRCodeModal.swift */; };
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; };
@ -1378,6 +1379,7 @@
B825849F2315024B001B41CB /* RSSFeedPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSSFeedPoller.swift; sourceTree = "<group>"; };
B845B4D3230CD09000D759F0 /* GroupChatPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatPoller.swift; sourceTree = "<group>"; };
B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = "<group>"; };
B84664F2234FE4530083A1CD /* Mention.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = "<group>"; };
B86BD08023399883000F5AE3 /* QRCodeModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeModal.swift; sourceTree = "<group>"; };
B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; };
@ -2652,6 +2654,7 @@
B8162F0222891AD600D46544 /* FriendRequestView.swift */,
B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */,
24A830A12293CD0100F4CAC0 /* LokiP2PServer.swift */,
B84664F2234FE4530083A1CD /* Mention.swift */,
B89841E222B7579F00B1BDC6 /* NewConversationVC.swift */,
B8258491230FA5DA001B41CB /* ScanQRCodeVC.h */,
B8258492230FA5E9001B41CB /* ScanQRCodeVC.m */,
@ -3879,6 +3882,7 @@
345BC30C2047030700257B7C /* OWS2FASettingsViewController.m in Sources */,
340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */,
34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */,
B84664F3234FE4540083A1CD /* Mention.swift in Sources */,
34D1F0C01F8EC1760066283D /* MessageRecipientStatusUtils.swift in Sources */,
45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */,
34277A5E20751BDC006049F2 /* OWSQuotedMessageView.m in Sources */,

@ -0,0 +1,13 @@
@objc(LKMention)
public final class Mention : NSObject {
@objc public let locationInString: UInt
@objc public let hexEncodedPublicKey: String
@objc public let displayName: String
@objc public init(locationInString: UInt, hexEncodedPublicKey: String, displayName: String) {
self.locationInString = locationInString
self.hexEncodedPublicKey = hexEncodedPublicKey
self.displayName = displayName
}
}

@ -3,7 +3,7 @@
@objc(LKUserSelectionView)
final class UserSelectionView : UIView, UITableViewDataSource, UITableViewDelegate {
@objc var users: [String] = [] { didSet { tableView.reloadData(); tableView.contentOffset = CGPoint.zero } }
@objc var users: [String] = [] { didSet { tableView.reloadData() } }
@objc var hasGroupContext = false
@objc var delegate: UserSelectionViewDelegate?

@ -213,7 +213,10 @@ typedef enum : NSUInteger {
@property (nonatomic) CGFloat extraContentInsetPadding;
@property (nonatomic) CGFloat contentInsetBottom;
@property (nonatomic) NSInteger mentionStartIndex;
// Mentions
@property (nonatomic) NSInteger currentMentionStartIndex;
@property (nonatomic) NSMutableArray<LKMention *> *mentions;
@property (nonatomic) NSString *oldText;
@end
@ -259,7 +262,8 @@ typedef enum : NSUInteger {
self.scrollContinuity = kScrollContinuityBottom;
_mentionStartIndex = -1;
_currentMentionStartIndex = -1;
_mentions = [NSMutableArray new];
}
#pragma mark - Dependencies
@ -3018,6 +3022,9 @@ typedef enum : NSUInteger {
{
[self tryToSendAttachments:attachments messageText:messageText];
[self.inputToolbar clearTextMessageAnimated:NO];
self.oldText = @"";
self.currentMentionStartIndex = -1;
self.mentions = @[].mutableCopy;
// we want to already be at the bottom when the user returns, rather than have to watch
// the new message scroll into view.
@ -3769,32 +3776,74 @@ typedef enum : NSUInteger {
- (void)textViewDidChange:(UITextView *)textView
{
if (textView.text.length == 0) { return; }
[self.typingIndicators didStartTypingOutgoingInputInThread:self.thread];
NSUInteger currentEndIndex = textView.text.length - 1;
unichar lastCharacter = [textView.text characterAtIndex:currentEndIndex];
if (lastCharacter == '@') {
NSArray<NSString *> *userIDs = [LKAPI getUserIDsFor:@"" in:self.thread.uniqueId];
self.mentionStartIndex = (NSInteger)currentEndIndex + 1;
[self.inputToolbar showUserSelectionViewFor:userIDs in:self.thread];
} else if ([NSCharacterSet.whitespaceAndNewlineCharacterSet characterIsMember:lastCharacter]) {
self.mentionStartIndex = -1;
[self.inputToolbar hideUserSelectionView];
} else {
if (self.mentionStartIndex != -1) {
NSString *query = [textView.text substringFromIndex:(NSUInteger)self.mentionStartIndex];
NSArray<NSString *> *userIDs = [LKAPI getUserIDsFor:query in:self.thread.uniqueId];
// Prepare
NSString *newText = textView.text;
// Typing indicators
if (newText.length > 0) {
[self.typingIndicators didStartTypingOutgoingInputInThread:self.thread];
}
// Mentions
BOOL isBackspace = newText.length < self.oldText.length;
if (isBackspace) {
self.currentMentionStartIndex = -1;
for (LKMention *mention in self.mentions) {
BOOL isValid;
if (mention.locationInString > (NSUInteger)MAX((NSInteger)newText.length - 1, 0)) {
isValid = NO;
} else {
isValid = [[newText substringFromIndex:mention.locationInString] hasPrefix:[NSString stringWithFormat:@"@%@", mention.displayName]];
}
if (!isValid) {
[self.mentions removeObject:mention];
}
}
} else if (newText.length > 0) {
NSUInteger currentEndIndex = newText.length - 1;
unichar lastCharacter = [newText characterAtIndex:currentEndIndex];
if (lastCharacter == '@') {
NSArray<NSString *> *userIDs = [LKAPI getUserIDsFor:@"" in:self.thread.uniqueId];
self.currentMentionStartIndex = (NSInteger)currentEndIndex;
[self.inputToolbar showUserSelectionViewFor:userIDs in:self.thread];
} else if ([NSCharacterSet.whitespaceAndNewlineCharacterSet characterIsMember:lastCharacter]) {
self.currentMentionStartIndex = -1;
[self.inputToolbar hideUserSelectionView];
} else {
if (self.currentMentionStartIndex != -1) {
NSString *query = [newText substringFromIndex:(NSUInteger)self.currentMentionStartIndex + 1]; // + 1 to get rid of the @
NSArray<NSString *> *userIDs = [LKAPI getUserIDsFor:query in:self.thread.uniqueId];
[self.inputToolbar showUserSelectionViewFor:userIDs in:self.thread];
}
}
}
self.oldText = newText;
}
- (void)handleUserSelected:(NSString *)user from:(LKUserSelectionView *)userSelectionView
- (void)handleUserSelected:(NSString *)hexEncodedPublicKey from:(LKUserSelectionView *)userSelectionView
{
NSUInteger mentionStartIndex = (NSUInteger)self.currentMentionStartIndex;
__block NSString *displayName;
[OWSPrimaryStorage.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
NSString *collection = [NSString stringWithFormat:@"%@.%llu", LKGroupChatAPI.publicChatServer, LKGroupChatAPI.publicChatServerID];
displayName = [transaction objectForKey:hexEncodedPublicKey inCollection:collection];
}];
LKMention *mention = [[LKMention alloc] initWithLocationInString:mentionStartIndex hexEncodedPublicKey:hexEncodedPublicKey displayName:displayName];
[self.mentions addObject:mention];
NSString *oldText = self.inputToolbar.messageText;
NSUInteger mentionStartIndex = (NSUInteger)self.mentionStartIndex;
NSString *newText = [oldText stringByReplacingCharactersInRange:NSMakeRange(mentionStartIndex, oldText.length - mentionStartIndex) withString:user];
NSString *newText = [oldText stringByReplacingCharactersInRange:NSMakeRange(mentionStartIndex, oldText.length - mentionStartIndex) withString:[NSString stringWithFormat:@"@%@", displayName]];
[self.inputToolbar setMessageText:newText animated:NO];
[self.inputToolbar hideUserSelectionView];
}
- (NSString *)getMessageBody
{
NSString *result = self.inputToolbar.messageText;
NSUInteger shift = 0;
for (LKMention *mention in self.mentions) {
NSRange range = NSMakeRange(mention.locationInString + shift, mention.displayName.length + 1); // + 1 to include the @
shift = shift + mention.hexEncodedPublicKey.length - mention.displayName.length;
result = [result stringByReplacingCharactersInRange:range withString:[[NSString alloc] initWithFormat:@"@%@", mention.hexEncodedPublicKey]];
}
return result;
}
- (void)inputTextViewSendMessagePressed
@ -4045,6 +4094,9 @@ typedef enum : NSUInteger {
{
[self tryToSendAttachments:attachments messageText:messageText];
[self.inputToolbar clearTextMessageAnimated:NO];
self.oldText = @"";
self.currentMentionStartIndex = -1;
self.mentions = @[].mutableCopy;
[self dismissViewControllerAnimated:YES completion:nil];
// We always want to scroll to the bottom of the conversation after the local user
@ -4415,7 +4467,7 @@ typedef enum : NSUInteger {
[BenchManager startEventWithTitle:@"Send Message milestone: toggleDefaultKeyboard completed"
eventId:@"fromSendUntil_toggleDefaultKeyboard"];
[self tryToSendTextMessage:self.inputToolbar.messageText updateKeyboardState:YES];
[self tryToSendTextMessage:[self getMessageBody] updateKeyboardState:YES];
}
- (void)tryToSendTextMessage:(NSString *)text updateKeyboardState:(BOOL)updateKeyboardState
@ -4473,6 +4525,9 @@ typedef enum : NSUInteger {
[BenchManager benchWithTitle:@"clearTextMessageAnimated"
block:^{
[self.inputToolbar clearTextMessageAnimated:YES];
self.oldText = @"";
self.currentMentionStartIndex = -1;
self.mentions = @[].mutableCopy;
}];
[BenchManager completeEventWithEventId:@"fromSendUntil_clearTextMessageAnimated"];

Loading…
Cancel
Save