parent
92477c78b7
commit
0e9c9a9bb3
|
@ -256,13 +256,21 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[self.footerView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
|
||||
[self.footerView autoPinWidthToSuperview];
|
||||
|
||||
UITapGestureRecognizer *tap =
|
||||
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
||||
[self addGestureRecognizer:tap];
|
||||
UITapGestureRecognizer *mediaTap =
|
||||
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMediaTapGesture:)];
|
||||
[self.mediaMaskingView addGestureRecognizer:mediaTap];
|
||||
|
||||
UILongPressGestureRecognizer *longPress =
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
|
||||
[self addGestureRecognizer:longPress];
|
||||
UITapGestureRecognizer *textTap =
|
||||
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTextTapGesture:)];
|
||||
[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 alloc] initWithDirection:PanDirectionHorizontal
|
||||
|
@ -337,6 +345,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
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
|
||||
{
|
||||
// This should always be valid for the appropriate cell types.
|
||||
|
@ -830,7 +846,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
- (void)addCaptionIfNecessary
|
||||
{
|
||||
if (self.viewItem.hasText) {
|
||||
if (self.hasText) {
|
||||
[self loadForTextDisplay];
|
||||
} else {
|
||||
[self.contentConstraints addObject:[self.textBubbleImageView autoSetDimension:ALDimensionHeight toSize:0]];
|
||||
|
@ -949,7 +965,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
self.mediaMaskingView.isOutgoing = self.isOutgoing;
|
||||
// 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 updateMask];
|
||||
}
|
||||
|
@ -1002,7 +1018,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
CGSize mediaContentSize = CGSizeZero;
|
||||
CGSize textContentSize = CGSizeZero;
|
||||
|
||||
if (self.viewItem.hasText) {
|
||||
if (self.hasText) {
|
||||
textContentSize = [self textBubbleSizeForContentWidth:contentWidth];
|
||||
}
|
||||
switch (self.cellType) {
|
||||
|
@ -1208,72 +1224,110 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
#pragma mark - Gesture recognizers
|
||||
|
||||
- (void)handleTapGesture:(UITapGestureRecognizer *)sender
|
||||
- (void)handleTextTapGesture:(UITapGestureRecognizer *)sender
|
||||
{
|
||||
OWSAssert(self.delegate);
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateRecognized) {
|
||||
|
||||
if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
|
||||
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
|
||||
if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
|
||||
[self.delegate didTapFailedOutgoingMessage:outgoingMessage];
|
||||
return;
|
||||
} else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) {
|
||||
// Ignore taps on outgoing messages being sent.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (self.cellType) {
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
if (self.displayableText.isTextTruncated) {
|
||||
[self.delegate didTapTruncatedTextMessage:self.viewItem];
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (sender.state != UIGestureRecognizerStateRecognized) {
|
||||
DDLogInfo(@"%@ Ignoring tap on message: %@", self.logTag, self.viewItem.interaction.debugDescription);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
|
||||
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
|
||||
if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
|
||||
[self.delegate didTapFailedOutgoingMessage:outgoingMessage];
|
||||
return;
|
||||
} else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) {
|
||||
// Ignore taps on outgoing messages being sent.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (self.hasText && self.displayableText.isTextTruncated) {
|
||||
[self.delegate didTapTruncatedTextMessage:self.viewItem];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)sender
|
||||
- (void)handleMediaTapGesture:(UITapGestureRecognizer *)sender
|
||||
{
|
||||
OWSAssert(self.delegate);
|
||||
|
||||
if (sender.state != UIGestureRecognizerStateRecognized) {
|
||||
DDLogInfo(@"%@ Ignoring tap on message: %@", self.logTag, self.viewItem.interaction.debugDescription);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.viewItem.interaction.interactionType == OWSInteractionType_OutgoingMessage) {
|
||||
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)self.viewItem.interaction;
|
||||
if (outgoingMessage.messageState == TSOutgoingMessageStateUnsent) {
|
||||
[self.delegate didTapFailedOutgoingMessage:outgoingMessage];
|
||||
return;
|
||||
} else if (outgoingMessage.messageState == TSOutgoingMessageStateAttemptingOut) {
|
||||
// Ignore taps on outgoing messages being sent.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (self.cellType) {
|
||||
case OWSMessageCellType_Unknown:
|
||||
break;
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
if (self.displayableText.isTextTruncated) {
|
||||
[self.delegate didTapTruncatedTextMessage:self.viewItem];
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (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 showMenuController:location];
|
||||
[self showTextMenuController:location];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleMediaLongPressGesture:(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 showMediaMenuController:location];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1340,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
#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
|
||||
|
@ -1301,7 +1355,29 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
// We use custom action selectors so that we can control
|
||||
// the ordering of the actions in the menu.
|
||||
NSArray *menuItems = self.viewItem.menuControllerItems;
|
||||
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,
|
||||
// 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.mediaMenuControllerItems;
|
||||
[UIMenuController sharedMenuController].menuItems = menuItems;
|
||||
CGRect targetRect = CGRectMake(fromLocation.x, fromLocation.y, 1, 1);
|
||||
[[UIMenuController sharedMenuController] setTargetRect:targetRect inView:self];
|
||||
|
@ -1313,19 +1389,29 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return [self.viewItem canPerformAction:action];
|
||||
}
|
||||
|
||||
- (void)copyAction:(nullable id)sender
|
||||
- (void)copyTextAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem copyAction];
|
||||
[self.viewItem copyTextAction];
|
||||
}
|
||||
|
||||
- (void)shareAction:(nullable id)sender
|
||||
- (void)copyMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem shareAction];
|
||||
[self.viewItem copyMediaAction];
|
||||
}
|
||||
|
||||
- (void)saveAction:(nullable id)sender
|
||||
- (void)shareTextAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem saveAction];
|
||||
[self.viewItem shareTextAction];
|
||||
}
|
||||
|
||||
- (void)shareMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem shareMediaAction];
|
||||
}
|
||||
|
||||
- (void)saveMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem saveMediaAction];
|
||||
}
|
||||
|
||||
- (void)deleteAction:(nullable id)sender
|
||||
|
|
|
@ -90,11 +90,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
|||
|
||||
#pragma mark - UIMenuController
|
||||
|
||||
- (NSArray<UIMenuItem *> *)menuControllerItems;
|
||||
- (NSArray<UIMenuItem *> *)textMenuControllerItems;
|
||||
- (NSArray<UIMenuItem *> *)mediaMenuControllerItems;
|
||||
|
||||
- (BOOL)canPerformAction:(SEL)action;
|
||||
- (void)copyAction;
|
||||
- (void)shareAction;
|
||||
- (void)saveAction;
|
||||
- (void)copyMediaAction;
|
||||
- (void)copyTextAction;
|
||||
- (void)shareMediaAction;
|
||||
- (void)shareTextAction;
|
||||
- (void)saveMediaAction;
|
||||
- (void)deleteAction;
|
||||
- (SEL)metadataActionSelector;
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
return @"OWSMessageCellType_GenericAttachment";
|
||||
case OWSMessageCellType_DownloadingAttachment:
|
||||
return @"OWSMessageCellType_DownloadingAttachment";
|
||||
case OWSMessageCellType_Unknown:
|
||||
return @"OWSMessageCellType_Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,41 +480,70 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
|
||||
#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 @[
|
||||
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SHARE_ACTION",
|
||||
@"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",
|
||||
@"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.copyActionSelector],
|
||||
action:self.copyMediaActionSelector],
|
||||
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_DELETE_ACTION",
|
||||
@"Short name for edit menu item to delete contents of media message.")
|
||||
action:self.deleteActionSelector],
|
||||
// TODO: Do we want a save action?
|
||||
[[UIMenuItem alloc] initWithTitle:NSLocalizedString(@"EDIT_ITEM_SAVE_ACTION",
|
||||
@"Short name for edit menu item to save contents of media message.")
|
||||
action:self.saveActionSelector],
|
||||
action:self.saveMediaActionSelector],
|
||||
];
|
||||
}
|
||||
|
||||
- (SEL)copyActionSelector
|
||||
- (SEL)copyTextActionSelector
|
||||
{
|
||||
return NSSelectorFromString(@"copyAction:");
|
||||
return NSSelectorFromString(@"copyTextAction:");
|
||||
}
|
||||
|
||||
- (SEL)saveActionSelector
|
||||
- (SEL)copyMediaActionSelector
|
||||
{
|
||||
return NSSelectorFromString(@"saveAction:");
|
||||
return NSSelectorFromString(@"copyMediaAction:");
|
||||
}
|
||||
|
||||
- (SEL)shareActionSelector
|
||||
- (SEL)saveMediaActionSelector
|
||||
{
|
||||
return NSSelectorFromString(@"shareAction:");
|
||||
return NSSelectorFromString(@"saveMediaAction:");
|
||||
}
|
||||
|
||||
- (SEL)shareTextActionSelector
|
||||
{
|
||||
return NSSelectorFromString(@"shareTextAction:");
|
||||
}
|
||||
|
||||
- (SEL)shareMediaActionSelector
|
||||
{
|
||||
return NSSelectorFromString(@"shareMediaAction:");
|
||||
}
|
||||
|
||||
- (SEL)deleteActionSelector
|
||||
|
@ -528,12 +559,16 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
// We only use custom actions in UIMenuController.
|
||||
- (BOOL)canPerformAction:(SEL)action
|
||||
{
|
||||
if (action == self.copyActionSelector) {
|
||||
return [self hasActionContent];
|
||||
} else if (action == self.saveActionSelector) {
|
||||
return [self canSave];
|
||||
} else if (action == self.shareActionSelector) {
|
||||
return [self hasActionContent];
|
||||
if (action == self.copyTextActionSelector) {
|
||||
return [self hasTextActionContent];
|
||||
} else if (action == self.copyMediaActionSelector) {
|
||||
return [self hasMediaActionContent];
|
||||
} else if (action == self.saveMediaActionSelector) {
|
||||
return [self canSaveMedia];
|
||||
} else if (action == self.shareTextActionSelector) {
|
||||
return [self hasTextActionContent];
|
||||
} else if (action == self.shareMediaActionSelector) {
|
||||
return [self hasMediaActionContent];
|
||||
} else if (action == self.deleteActionSelector) {
|
||||
return YES;
|
||||
} else if (action == self.metadataActionSelector) {
|
||||
|
@ -543,14 +578,40 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
}
|
||||
}
|
||||
|
||||
- (void)copyAction
|
||||
- (void)copyTextAction
|
||||
{
|
||||
switch (self.messageCellType) {
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
case OWSMessageCellType_StillImage:
|
||||
case OWSMessageCellType_AnimatedImage:
|
||||
case OWSMessageCellType_Audio:
|
||||
case OWSMessageCellType_Video:
|
||||
case OWSMessageCellType_GenericAttachment: {
|
||||
OWSAssert(self.displayableText);
|
||||
[UIPasteboard.generalPasteboard setString:self.displayableText.fullText];
|
||||
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_AnimatedImage:
|
||||
case OWSMessageCellType_Audio:
|
||||
|
@ -576,14 +637,38 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
}
|
||||
}
|
||||
|
||||
- (void)shareAction
|
||||
- (void)shareTextAction
|
||||
{
|
||||
switch (self.messageCellType) {
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
case OWSMessageCellType_StillImage:
|
||||
case OWSMessageCellType_AnimatedImage:
|
||||
case OWSMessageCellType_Audio:
|
||||
case OWSMessageCellType_Video:
|
||||
case OWSMessageCellType_GenericAttachment: {
|
||||
OWSAssert(self.displayableText);
|
||||
[AttachmentSharing showShareUIForText:self.displayableText.fullText];
|
||||
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_AnimatedImage:
|
||||
case OWSMessageCellType_Audio:
|
||||
|
@ -598,9 +683,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)canSave
|
||||
- (BOOL)canSaveMedia
|
||||
{
|
||||
switch (self.messageCellType) {
|
||||
case OWSMessageCellType_Unknown:
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
return NO;
|
||||
|
@ -619,9 +705,10 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
}
|
||||
}
|
||||
|
||||
- (void)saveAction
|
||||
- (void)saveMediaAction
|
||||
{
|
||||
switch (self.messageCellType) {
|
||||
case OWSMessageCellType_Unknown:
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
OWSFail(@"%@ Cannot save text data.", self.logTag);
|
||||
|
@ -668,13 +755,18 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
|||
[self.interaction remove];
|
||||
}
|
||||
|
||||
- (BOOL)hasActionContent
|
||||
- (BOOL)hasTextActionContent
|
||||
{
|
||||
return self.hasText && self.displayableText.fullText.length > 0;
|
||||
}
|
||||
|
||||
- (BOOL)hasMediaActionContent
|
||||
{
|
||||
switch (self.messageCellType) {
|
||||
case OWSMessageCellType_Unknown:
|
||||
case OWSMessageCellType_TextMessage:
|
||||
case OWSMessageCellType_OversizeTextMessage:
|
||||
OWSAssert(self.displayableText);
|
||||
return self.displayableText.fullText.length > 0;
|
||||
return NO;
|
||||
case OWSMessageCellType_StillImage:
|
||||
case OWSMessageCellType_AnimatedImage:
|
||||
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.
|
||||
if (sender.state == UIGestureRecognizerStateBegan) {
|
||||
|
@ -325,7 +325,30 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[[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;
|
||||
CGPoint location = [sender locationInView:self.view];
|
||||
CGRect targetRect = CGRectMake(location.x, location.y, 1, 1);
|
||||
|
@ -342,19 +365,29 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return [self.viewItem canPerformAction:action];
|
||||
}
|
||||
|
||||
- (void)copyAction:(nullable id)sender
|
||||
- (void)copyTextAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem copyAction];
|
||||
[self.viewItem copyTextAction];
|
||||
}
|
||||
|
||||
- (void)shareAction:(nullable id)sender
|
||||
- (void)copyMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem shareAction];
|
||||
[self.viewItem copyMediaAction];
|
||||
}
|
||||
|
||||
- (void)saveAction:(nullable id)sender
|
||||
- (void)shareTextAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem saveAction];
|
||||
[self.viewItem shareTextAction];
|
||||
}
|
||||
|
||||
- (void)shareMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem shareMediaAction];
|
||||
}
|
||||
|
||||
- (void)saveMediaAction:(nullable id)sender
|
||||
{
|
||||
[self.viewItem saveMediaAction];
|
||||
}
|
||||
|
||||
- (void)deleteAction:(nullable id)sender
|
||||
|
|
Loading…
Reference in New Issue