From d99054d895f9e6b760b401cdffebe75e900c0b7c Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 3 Apr 2018 22:31:13 -0400 Subject: [PATCH] Reply menu item MVP - [x] populate from menu - [] send quoted message TODO - [] thumbnail - [] paperclip icon showing for text message - [] cancel button asset - [] fonts - [] colors - [] adjust content inset/offset when showing quote edit NICE TO HAVE - [] animate presentation - [] animate dismiss - [] non-paperclip icon for generic attachments // FREEBIE --- .../Cells/ConversationViewCell.h | 1 + .../ConversationView/Cells/OWSMessageCell.m | 7 ++++++ .../ConversationInputToolbar.m | 11 +++++---- .../ConversationViewController.m | 24 +++++++++++++++++++ .../ConversationView/ConversationViewItem.m | 23 ++++++++++++++---- .../translations/en.lproj/Localizable.strings | 6 ++--- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/Cells/ConversationViewCell.h b/Signal/src/ViewControllers/ConversationView/Cells/ConversationViewCell.h index db315d5f7..e4f5baec3 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/ConversationViewCell.h +++ b/Signal/src/ViewControllers/ConversationView/Cells/ConversationViewCell.h @@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN viewItem:(ConversationViewItem *)conversationItem; - (void)showMetadataViewForViewItem:(ConversationViewItem *)conversationItem; +- (void)conversationCell:(ConversationViewCell *)cell didTapReplyForViewItem:(ConversationViewItem *)conversationItem; #pragma mark - System Cell diff --git a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m index 844610a44..58f5b30c7 100644 --- a/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m +++ b/Signal/src/ViewControllers/ConversationView/Cells/OWSMessageCell.m @@ -1899,6 +1899,13 @@ CG_INLINE CGSize CGSizeCeil(CGSize size) [self.delegate showMetadataViewForViewItem:self.viewItem]; } +- (void)replyAction:(nullable id)sender +{ + OWSAssert([self.viewItem.interaction isKindOfClass:[TSMessage class]]); + + [self.delegate conversationCell:self didTapReplyForViewItem:self.viewItem]; +} + - (BOOL)canBecomeFirstResponder { return self.isPresentingMenuController; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m b/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m index fc3fa1954..791c1938b 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationInputToolbar.m @@ -252,13 +252,14 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5; - (void)setQuotedMessage:(TSQuotedMessage *)quotedMessage { + // TODO update existing preview with message in case we switch which message we're quoting. + if (self.quotedMessagePreview) { + [self clearQuotedMessage]; + } OWSAssert(self.quotedMessagePreview == nil); - // TODO update preview view with message in case we switch which message we're quoting. - if (quotedMessage) { - self.quotedMessagePreview = [[QuotedReplyPreview alloc] initWithQuotedMessage:quotedMessage]; - self.quotedMessagePreview.delegate = self; - } + self.quotedMessagePreview = [[QuotedReplyPreview alloc] initWithQuotedMessage:quotedMessage]; + self.quotedMessagePreview.delegate = self; // TODO animate [self.contentStackView insertArrangedSubview:self.quotedMessagePreview atIndex:0]; diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 8bba6ce45..5cb47cac5 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -2158,6 +2158,30 @@ typedef enum : NSUInteger { [self.navigationController pushViewController:view animated:YES]; } +- (void)conversationCell:(ConversationViewCell *)cell didTapReplyForViewItem:(ConversationViewItem *)conversationItem +{ + DDLogDebug(@"%@ user did tap reply", self.logTag); + + TSMessage *message = (TSMessage *)conversationItem.interaction; + if (![message isKindOfClass:[TSMessage class]]) { + OWSFail(@"%@ unexpected reply message: %@", self.logTag, message); + return; + } + + __block TSQuotedMessage *quotedMessage; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { + quotedMessage = [OWSMessageUtils quotedMessageForMessage:message transaction:transaction]; + }]; + + if (![quotedMessage isKindOfClass:[TSQuotedMessage class]]) { + OWSFail(@"%@ unexpected quotedMessage: %@", self.logTag, quotedMessage); + return; + } + + [self.inputToolbar setQuotedMessage:quotedMessage]; + [self.inputToolbar beginEditingTextMessage]; +} + #pragma mark - System Messages - (void)didTapSystemMessageWithInteraction:(TSInteraction *)interaction diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m index a32338cdc..b64d95f7b 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewItem.m @@ -542,18 +542,21 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) - (NSArray *)textMenuControllerItems { return @[ - [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_COPY_ACTION", - @"Short name for edit menu item to copy contents of media message.") - action:self.copyTextActionSelector], [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_MESSAGE_METADATA_ACTION", @"Short name for edit menu item to show message metadata.") action:self.metadataActionSelector], + [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_COPY_ACTION", + @"Short name for edit menu item to copy contents of media message.") + action:self.copyTextActionSelector], + [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"REPLY_ITEM_ACTION", + @"Short name for edit menu item to reply to a message.") + action:self.replyActionSelector], // FIXME: when deleting a caption, users will be surprised that it also deletes the attachment. // We either need to implement a way to remove the caption separate from the attachment // or make a design change which clarifies that the whole message is getting deleted. [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION", - @"Short name for edit menu item to delete contents of media message.") - action:self.deleteActionSelector] + @"Short name for edit menu item to delete contents of media message.") + action:self.deleteActionSelector] ]; } - (NSArray *)mediaMenuControllerItems @@ -565,6 +568,9 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_COPY_ACTION", @"Short name for edit menu item to copy contents of media message.") action:self.copyMediaActionSelector], + [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"REPLY_ITEM_ACTION", + @"Short name for edit menu item to reply to a message.") + action:self.replyActionSelector], [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION", @"Short name for edit menu item to delete contents of media message.") action:self.deleteActionSelector], @@ -604,6 +610,11 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return NSSelectorFromString(@"deleteAction:"); } +- (SEL)replyActionSelector +{ + return NSSelectorFromString(@"replyAction:"); +} + - (SEL)metadataActionSelector { return NSSelectorFromString(@"metadataAction:"); @@ -626,6 +637,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType) return YES; } else if (action == self.metadataActionSelector) { return YES; + } else if (action == self.replyActionSelector) { + return YES; } else { return NO; } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 5c5fcc419..2c5c420c9 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -184,9 +184,6 @@ /* Error indicating the backup import could not import the user's data. */ "BACKUP_IMPORT_ERROR_COULD_NOT_IMPORT" = "Backup could not be imported."; -/* Indicates that the backup import is checking for an existing backup. */ -"BACKUP_IMPORT_PHASE_CHECK_BACKUP" = "Checking Backup State"; - /* Indicates that the backup import is being configured. */ "BACKUP_IMPORT_PHASE_CONFIGURATION" = "Configuring Backup"; @@ -1519,6 +1516,9 @@ /* Alert title after wrong guess for 'two-factor auth pin' reminder activity */ "REMINDER_2FA_WRONG_PIN_ALERT_TITLE" = "That is not the correct PIN."; +/* Short name for edit menu item to reply to a message. */ +"REPLY_ITEM_ACTION" = "Reply"; + /* No comment provided by engineer. */ "REREGISTER_FOR_PUSH" = "Re-register for push notifications";