Separate gestures for text/vs media

// FREEBIE
pull/1/head
sdkjfhsdkjhfsdlkjhfsdf 7 years ago
parent 92477c78b7
commit 0e9c9a9bb3

@ -256,13 +256,21 @@ NS_ASSUME_NONNULL_BEGIN
[self.footerView autoPinEdgeToSuperviewEdge:ALEdgeBottom]; [self.footerView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[self.footerView autoPinWidthToSuperview]; [self.footerView autoPinWidthToSuperview];
UITapGestureRecognizer *tap = UITapGestureRecognizer *mediaTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMediaTapGesture:)];
[self addGestureRecognizer:tap]; [self.mediaMaskingView addGestureRecognizer:mediaTap];
UILongPressGestureRecognizer *longPress = UITapGestureRecognizer *textTap =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)]; [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTextTapGesture:)];
[self addGestureRecognizer:longPress]; [self.textBubbleImageView addGestureRecognizer:textTap];
UILongPressGestureRecognizer *mediaLongPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleMediaLongPressGesture:)];
[self.mediaMaskingView addGestureRecognizer:mediaLongPress];
UILongPressGestureRecognizer *textLongPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTextLongPressGesture:)];
[self.textBubbleImageView addGestureRecognizer:textLongPress];
PanDirectionGestureRecognizer *panGesture = PanDirectionGestureRecognizer *panGesture =
[[PanDirectionGestureRecognizer alloc] initWithDirection:PanDirectionHorizontal [[PanDirectionGestureRecognizer alloc] initWithDirection:PanDirectionHorizontal
@ -337,6 +345,14 @@ NS_ASSUME_NONNULL_BEGIN
return self.viewItem.messageCellType; return self.viewItem.messageCellType;
} }
- (BOOL)hasText
{
// This should always be valid for the appropriate cell types.
OWSAssert(self.viewItem);
return self.viewItem.hasText;
}
- (nullable DisplayableText *)displayableText - (nullable DisplayableText *)displayableText
{ {
// This should always be valid for the appropriate cell types. // This should always be valid for the appropriate cell types.
@ -830,7 +846,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)addCaptionIfNecessary - (void)addCaptionIfNecessary
{ {
if (self.viewItem.hasText) { if (self.hasText) {
[self loadForTextDisplay]; [self loadForTextDisplay];
} else { } else {
[self.contentConstraints addObject:[self.textBubbleImageView autoSetDimension:ALDimensionHeight toSize:0]]; [self.contentConstraints addObject:[self.textBubbleImageView autoSetDimension:ALDimensionHeight toSize:0]];
@ -949,7 +965,7 @@ NS_ASSUME_NONNULL_BEGIN
self.mediaMaskingView.isOutgoing = self.isOutgoing; self.mediaMaskingView.isOutgoing = self.isOutgoing;
// Hide tail on attachments followed by a caption // Hide tail on attachments followed by a caption
self.mediaMaskingView.hideTail = self.viewItem.hasText; self.mediaMaskingView.hideTail = self.hasText;
self.mediaMaskingView.maskedSubview = view; self.mediaMaskingView.maskedSubview = view;
[self.mediaMaskingView updateMask]; [self.mediaMaskingView updateMask];
} }
@ -1002,7 +1018,7 @@ NS_ASSUME_NONNULL_BEGIN
CGSize mediaContentSize = CGSizeZero; CGSize mediaContentSize = CGSizeZero;
CGSize textContentSize = CGSizeZero; CGSize textContentSize = CGSizeZero;
if (self.viewItem.hasText) { if (self.hasText) {
textContentSize = [self textBubbleSizeForContentWidth:contentWidth]; textContentSize = [self textBubbleSizeForContentWidth:contentWidth];
} }
switch (self.cellType) { switch (self.cellType) {
@ -1208,72 +1224,110 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Gesture recognizers #pragma mark - Gesture recognizers
- (void)handleTapGesture:(UITapGestureRecognizer *)sender - (void)handleTextTapGesture:(UITapGestureRecognizer *)sender
{ {
OWSAssert(self.delegate); OWSAssert(self.delegate);
if (sender.state == UIGestureRecognizerStateRecognized) { if (sender.state != UIGestureRecognizerStateRecognized) {
DDLogInfo(@"%@ Ignoring tap on message: %@", self.logTag, self.viewItem.interaction.debugDescription);
return;
}
if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) { if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction; TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) { if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
[self.delegate didTapFailedOutgoingMessage:outgoingMessage]; [self.delegate didTapFailedOutgoingMessage:outgoingMessage];
return; return;
} else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) { } else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) {
// Ignore taps on outgoing messages being sent. // Ignore taps on outgoing messages being sent.
return; return;
}
} }
}
switch (self.cellType) { if (self.hasText && self.displayableText.isTextTruncated) {
case OWSMessageCellType_TextMessage: [self.delegate didTapTruncatedTextMessage:self.viewItem];
case OWSMessageCellType_OversizeTextMessage: return;
if (self.displayableText.isTextTruncated) { }
[self.delegate didTapTruncatedTextMessage:self.viewItem]; }
return;
} - (void)handleMediaTapGesture:(UITapGestureRecognizer *)sender
break; {
case OWSMessageCellType_StillImage: OWSAssert(self.delegate);
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.attachmentStream if (sender.state != UIGestureRecognizerStateRecognized) {
imageView:self.stillImageView]; DDLogInfo(@"%@ Ignoring tap on message: %@", self.logTag, self.viewItem.interaction.debugDescription);
break; return;
case OWSMessageCellType_AnimatedImage: }
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.attachmentStream if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
imageView:self.animatedImageView]; TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
break; if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
case OWSMessageCellType_Audio: [self.delegate didTapFailedOutgoingMessage:outgoingMessage];
[self.delegate didTapAudioViewItem:self.viewItem attachmentStream:self.attachmentStream]; return;
return; } else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) {
case OWSMessageCellType_Video: // Ignore taps on outgoing messages being sent.
[self.delegate didTapVideoViewItem:self.viewItem attachmentStream:self.attachmentStream]; return;
}
}
switch (self.cellType) {
case OWSMessageCellType_Unknown:
break;
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
if (self.displayableText.isTextTruncated) {
[self.delegate didTapTruncatedTextMessage:self.viewItem];
return; return;
case OWSMessageCellType_GenericAttachment:
[AttachmentSharing showShareUIForAttachment:self.attachmentStream];
break;
case OWSMessageCellType_DownloadingAttachment: {
OWSAssert(self.attachmentPointer);
if (self.attachmentPointer.state == TSAttachmentPointerStateFailed) {
[self.delegate didTapFailedIncomingAttachment:self.viewItem
attachmentPointer:self.attachmentPointer];
}
break;
} }
break;
case OWSMessageCellType_StillImage:
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.attachmentStream
imageView:self.stillImageView];
break;
case OWSMessageCellType_AnimatedImage:
[self.delegate didTapImageViewItem:self.viewItem
attachmentStream:self.attachmentStream
imageView:self.animatedImageView];
break;
case OWSMessageCellType_Audio:
[self.delegate didTapAudioViewItem:self.viewItem attachmentStream:self.attachmentStream];
return;
case OWSMessageCellType_Video:
[self.delegate didTapVideoViewItem:self.viewItem attachmentStream:self.attachmentStream];
return;
case OWSMessageCellType_GenericAttachment:
[AttachmentSharing showShareUIForAttachment:self.attachmentStream];
break;
case OWSMessageCellType_DownloadingAttachment: {
OWSAssert(self.attachmentPointer);
if (self.attachmentPointer.state == TSAttachmentPointerStateFailed) {
[self.delegate didTapFailedIncomingAttachment:self.viewItem attachmentPointer:self.attachmentPointer];
}
break;
} }
}
}
DDLogInfo(@"%@ Ignoring tap on message: %@", self.logTag, self.viewItem.interaction.debugDescription); - (void)handleTextLongPressGesture:(UILongPressGestureRecognizer *)sender
{
OWSAssert(self.delegate);
// We "eagerly" respond when the long press begins, not when it ends.
if (sender.state == UIGestureRecognizerStateBegan) {
CGPoint location = [sender locationInView:self];
[self showTextMenuController:location];
} }
} }
- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)sender - (void)handleMediaLongPressGesture:(UILongPressGestureRecognizer *)sender
{ {
OWSAssert(self.delegate); OWSAssert(self.delegate);
// We "eagerly" respond when the long press begins, not when it ends. // We "eagerly" respond when the long press begins, not when it ends.
if (sender.state == UIGestureRecognizerStateBegan) { if (sender.state == UIGestureRecognizerStateBegan) {
CGPoint location = [sender locationInView:self]; CGPoint location = [sender locationInView:self];
[self showMenuController:location]; [self showMediaMenuController:location];
} }
} }
@ -1286,7 +1340,29 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - UIMenuController #pragma mark - UIMenuController
- (void)showMenuController:(CGPoint)fromLocation - (void)showTextMenuController:(CGPoint)fromLocation
{
// We don't want taps on messages to hide the keyboard,
// so we only let messages become first responder
// while they are trying to present the menu controller.
self.isPresentingMenuController = YES;
[self becomeFirstResponder];
if ([UIMenuController sharedMenuController].isMenuVisible) {
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
}
// We use custom action selectors so that we can control
// the ordering of the actions in the menu.
NSArray *menuItems = self.viewItem.textMenuControllerItems;
[UIMenuController sharedMenuController].menuItems = menuItems;
CGRect targetRect = CGRectMake(fromLocation.x, fromLocation.y, 1, 1);
[[UIMenuController sharedMenuController] setTargetRect:targetRect inView:self];
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
}
- (void)showMediaMenuController:(CGPoint)fromLocation
{ {
// We don't want taps on messages to hide the keyboard, // We don't want taps on messages to hide the keyboard,
// so we only let messages become first responder // so we only let messages become first responder
@ -1301,7 +1377,7 @@ NS_ASSUME_NONNULL_BEGIN
// We use custom action selectors so that we can control // We use custom action selectors so that we can control
// the ordering of the actions in the menu. // the ordering of the actions in the menu.
NSArray *menuItems = self.viewItem.menuControllerItems; NSArray *menuItems = self.viewItem.mediaMenuControllerItems;
[UIMenuController sharedMenuController].menuItems = menuItems; [UIMenuController sharedMenuController].menuItems = menuItems;
CGRect targetRect = CGRectMake(fromLocation.x, fromLocation.y, 1, 1); CGRect targetRect = CGRectMake(fromLocation.x, fromLocation.y, 1, 1);
[[UIMenuController sharedMenuController] setTargetRect:targetRect inView:self]; [[UIMenuController sharedMenuController] setTargetRect:targetRect inView:self];
@ -1313,19 +1389,29 @@ NS_ASSUME_NONNULL_BEGIN
return [self.viewItem canPerformAction:action]; return [self.viewItem canPerformAction:action];
} }
- (void)copyAction:(nullable id)sender - (void)copyTextAction:(nullable id)sender
{
[self.viewItem copyTextAction];
}
- (void)copyMediaAction:(nullable id)sender
{
[self.viewItem copyMediaAction];
}
- (void)shareTextAction:(nullable id)sender
{ {
[self.viewItem copyAction]; [self.viewItem shareTextAction];
} }
- (void)shareAction:(nullable id)sender - (void)shareMediaAction:(nullable id)sender
{ {
[self.viewItem shareAction]; [self.viewItem shareMediaAction];
} }
- (void)saveAction:(nullable id)sender - (void)saveMediaAction:(nullable id)sender
{ {
[self.viewItem saveAction]; [self.viewItem saveMediaAction];
} }
- (void)deleteAction:(nullable id)sender - (void)deleteAction:(nullable id)sender

@ -90,11 +90,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
#pragma mark - UIMenuController #pragma mark - UIMenuController
- (NSArray<UIMenuItem *> *)menuControllerItems; - (NSArray<UIMenuItem *> *)textMenuControllerItems;
- (NSArray<UIMenuItem *> *)mediaMenuControllerItems;
- (BOOL)canPerformAction:(SEL)action; - (BOOL)canPerformAction:(SEL)action;
- (void)copyAction; - (void)copyMediaAction;
- (void)shareAction; - (void)copyTextAction;
- (void)saveAction; - (void)shareMediaAction;
- (void)shareTextAction;
- (void)saveMediaAction;
- (void)deleteAction; - (void)deleteAction;
- (SEL)metadataActionSelector; - (SEL)metadataActionSelector;

@ -34,6 +34,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return @"OWSMessageCellType_GenericAttachment"; return @"OWSMessageCellType_GenericAttachment";
case OWSMessageCellType_DownloadingAttachment: case OWSMessageCellType_DownloadingAttachment:
return @"OWSMessageCellType_DownloadingAttachment"; return @"OWSMessageCellType_DownloadingAttachment";
case OWSMessageCellType_Unknown:
return @"OWSMessageCellType_Unknown";
} }
} }
@ -478,41 +480,70 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
#pragma mark - UIMenuController #pragma mark - UIMenuController
- (NSArray<UIMenuItem *> *)menuControllerItems - (NSArray<UIMenuItem *> *)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_SHARE_ACTION",
@"Short name for edit menu item to share contents of media message.")
action:self.shareTextActionSelector],
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_MESSAGE_METADATA_ACTION",
@"Short name for edit menu item to show message metadata.")
action:self.metadataActionSelector],
// FIXME this is going to be confusing if the text/attachment look like separate entities.
// we can re-enable this once it's clear that deleting the text would also delete the attachment.
// [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION",
// @"Short name for edit menu item to delete contents of media
// message.")
// action:self.deleteActionSelector],
];
}
- (NSArray<UIMenuItem *> *)mediaMenuControllerItems
{ {
return @[ return @[
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SHARE_ACTION", [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SHARE_ACTION",
@"Short name for edit menu item to share contents of media message.") @"Short name for edit menu item to share contents of media message.")
action:self.shareActionSelector], action:self.shareMediaActionSelector],
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_MESSAGE_METADATA_ACTION", [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_MESSAGE_METADATA_ACTION",
@"Short name for edit menu item to show message metadata.") @"Short name for edit menu item to show message metadata.")
action:self.metadataActionSelector], action:self.metadataActionSelector],
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_COPY_ACTION", [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_COPY_ACTION",
@"Short name for edit menu item to copy contents of media message.") @"Short name for edit menu item to copy contents of media message.")
action:self.copyActionSelector], action:self.copyMediaActionSelector],
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION", [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION",
@"Short name for edit menu item to delete contents of media message.") @"Short name for edit menu item to delete contents of media message.")
action:self.deleteActionSelector], action:self.deleteActionSelector],
// TODO: Do we want a save action?
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SAVE_ACTION", [[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SAVE_ACTION",
@"Short name for edit menu item to save contents of media message.") @"Short name for edit menu item to save contents of media message.")
action:self.saveActionSelector], action:self.saveMediaActionSelector],
]; ];
} }
- (SEL)copyActionSelector - (SEL)copyTextActionSelector
{
return NSSelectorFromString(@"copyTextAction:");
}
- (SEL)copyMediaActionSelector
{ {
return NSSelectorFromString(@"copyAction:"); return NSSelectorFromString(@"copyMediaAction:");
} }
- (SEL)saveActionSelector - (SEL)saveMediaActionSelector
{ {
return NSSelectorFromString(@"saveAction:"); return NSSelectorFromString(@"saveMediaAction:");
} }
- (SEL)shareActionSelector - (SEL)shareTextActionSelector
{ {
return NSSelectorFromString(@"shareAction:"); return NSSelectorFromString(@"shareTextAction:");
}
- (SEL)shareMediaActionSelector
{
return NSSelectorFromString(@"shareMediaAction:");
} }
- (SEL)deleteActionSelector - (SEL)deleteActionSelector
@ -528,12 +559,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
// We only use custom actions in UIMenuController. // We only use custom actions in UIMenuController.
- (BOOL)canPerformAction:(SEL)action - (BOOL)canPerformAction:(SEL)action
{ {
if (action == self.copyActionSelector) { if (action == self.copyTextActionSelector) {
return [self hasActionContent]; return [self hasTextActionContent];
} else if (action == self.saveActionSelector) { } else if (action == self.copyMediaActionSelector) {
return [self canSave]; return [self hasMediaActionContent];
} else if (action == self.shareActionSelector) { } else if (action == self.saveMediaActionSelector) {
return [self hasActionContent]; return [self canSaveMedia];
} else if (action == self.shareTextActionSelector) {
return [self hasTextActionContent];
} else if (action == self.shareMediaActionSelector) {
return [self hasMediaActionContent];
} else if (action == self.deleteActionSelector) { } else if (action == self.deleteActionSelector) {
return YES; return YES;
} else if (action == self.metadataActionSelector) { } else if (action == self.metadataActionSelector) {
@ -543,14 +578,40 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
} }
} }
- (void)copyAction - (void)copyTextAction
{ {
switch (self.messageCellType) { switch (self.messageCellType) {
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_GenericAttachment: {
OWSAssert(self.displayableText); OWSAssert(self.displayableText);
[UIPasteboard.generalPasteboard setString:self.displayableText.fullText]; [UIPasteboard.generalPasteboard setString:self.displayableText.fullText];
break; break;
}
case OWSMessageCellType_DownloadingAttachment: {
OWSFail(@"%@ Can't copy not-yet-downloaded attachment", self.logTag);
break;
}
case OWSMessageCellType_Unknown: {
OWSFail(@"%@ No text to copy", self.logTag);
break;
}
}
}
- (void)copyMediaAction
{
switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: {
OWSFail(@"%@ No media to copy", self.logTag);
break;
}
case OWSMessageCellType_StillImage: case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio: case OWSMessageCellType_Audio:
@ -576,14 +637,38 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
} }
} }
- (void)shareAction - (void)shareTextAction
{ {
switch (self.messageCellType) { switch (self.messageCellType) {
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio:
case OWSMessageCellType_Video:
case OWSMessageCellType_GenericAttachment: {
OWSAssert(self.displayableText); OWSAssert(self.displayableText);
[AttachmentSharing showShareUIForText:self.displayableText.fullText]; [AttachmentSharing showShareUIForText:self.displayableText.fullText];
break; break;
}
case OWSMessageCellType_DownloadingAttachment: {
OWSFail(@"%@ Can't share not-yet-downloaded attachment", self.logTag);
break;
}
case OWSMessageCellType_Unknown: {
OWSFail(@"%@ No text to share", self.logTag)
}
}
}
- (void)shareMediaAction
{
switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage:
OWSFail(@"No media to share.");
break;
case OWSMessageCellType_StillImage: case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio: case OWSMessageCellType_Audio:
@ -598,9 +683,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
} }
} }
- (BOOL)canSave - (BOOL)canSaveMedia
{ {
switch (self.messageCellType) { switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
return NO; return NO;
@ -619,9 +705,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
} }
} }
- (void)saveAction - (void)saveMediaAction
{ {
switch (self.messageCellType) { switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
OWSFail(@"%@ Cannot save text data.", self.logTag); OWSFail(@"%@ Cannot save text data.", self.logTag);
@ -668,13 +755,18 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
[self.interaction remove]; [self.interaction remove];
} }
- (BOOL)hasActionContent - (BOOL)hasTextActionContent
{
return self.hasText && self.displayableText.fullText.length > 0;
}
- (BOOL)hasMediaActionContent
{ {
switch (self.messageCellType) { switch (self.messageCellType) {
case OWSMessageCellType_Unknown:
case OWSMessageCellType_TextMessage: case OWSMessageCellType_TextMessage:
case OWSMessageCellType_OversizeTextMessage: case OWSMessageCellType_OversizeTextMessage:
OWSAssert(self.displayableText); return NO;
return self.displayableText.fullText.length > 0;
case OWSMessageCellType_StillImage: case OWSMessageCellType_StillImage:
case OWSMessageCellType_AnimatedImage: case OWSMessageCellType_AnimatedImage:
case OWSMessageCellType_Audio: case OWSMessageCellType_Audio:

@ -311,7 +311,7 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (void)longPressGesture:(UIGestureRecognizer *)sender - (void)longPressTextGesture:(UIGestureRecognizer *)sender
{ {
// We "eagerly" respond when the long press begins, not when it ends. // We "eagerly" respond when the long press begins, not when it ends.
if (sender.state == UIGestureRecognizerStateBegan) { if (sender.state == UIGestureRecognizerStateBegan) {
@ -325,7 +325,30 @@ NS_ASSUME_NONNULL_BEGIN
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO]; [[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
} }
NSArray *menuItems = self.viewItem.menuControllerItems; NSArray *menuItems = self.viewItem.textMenuControllerItems;
[UIMenuController sharedMenuController].menuItems = menuItems;
CGPoint location = [sender locationInView:self.view];
CGRect targetRect = CGRectMake(location.x, location.y, 1, 1);
[[UIMenuController sharedMenuController] setTargetRect:targetRect inView:self.view];
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
}
}
- (void)longPressMediaGesture:(UIGestureRecognizer *)sender
{
// We "eagerly" respond when the long press begins, not when it ends.
if (sender.state == UIGestureRecognizerStateBegan) {
if (!self.viewItem) {
return;
}
[self.view becomeFirstResponder];
if ([UIMenuController sharedMenuController].isMenuVisible) {
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
}
NSArray *menuItems = self.viewItem.mediaMenuControllerItems;
[UIMenuController sharedMenuController].menuItems = menuItems; [UIMenuController sharedMenuController].menuItems = menuItems;
CGPoint location = [sender locationInView:self.view]; CGPoint location = [sender locationInView:self.view];
CGRect targetRect = CGRectMake(location.x, location.y, 1, 1); CGRect targetRect = CGRectMake(location.x, location.y, 1, 1);
@ -342,19 +365,29 @@ NS_ASSUME_NONNULL_BEGIN
return [self.viewItem canPerformAction:action]; return [self.viewItem canPerformAction:action];
} }
- (void)copyAction:(nullable id)sender - (void)copyTextAction:(nullable id)sender
{
[self.viewItem copyTextAction];
}
- (void)copyMediaAction:(nullable id)sender
{
[self.viewItem copyMediaAction];
}
- (void)shareTextAction:(nullable id)sender
{ {
[self.viewItem copyAction]; [self.viewItem shareTextAction];
} }
- (void)shareAction:(nullable id)sender - (void)shareMediaAction:(nullable id)sender
{ {
[self.viewItem shareAction]; [self.viewItem shareMediaAction];
} }
- (void)saveAction:(nullable id)sender - (void)saveMediaAction:(nullable id)sender
{ {
[self.viewItem saveAction]; [self.viewItem saveMediaAction];
} }
- (void)deleteAction:(nullable id)sender - (void)deleteAction:(nullable id)sender

Loading…
Cancel
Save