ConversationViewItem -> protocol

This commit is contained in:
Michael Kirk 2018-09-27 16:49:01 -06:00
parent f56ac96d31
commit 06eae47e09
21 changed files with 213 additions and 181 deletions

View File

@ -67,66 +67,67 @@ struct MessageActionBuilder {
}
}
extension ConversationViewItem {
@objc
class ConversationViewItemActions: NSObject {
@objc
func textActions(delegate: MessageActionsDelegate) -> [MenuAction] {
class func textActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
var actions: [MenuAction] = []
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(replyAction)
if self.hasBodyTextActionContent {
let copyTextAction = MessageActionBuilder.copyText(conversationViewItem: self, delegate: delegate)
if conversationViewItem.hasBodyTextActionContent {
let copyTextAction = MessageActionBuilder.copyText(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(copyTextAction)
}
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(deleteAction)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(showDetailsAction)
return actions
}
@objc
func mediaActions(delegate: MessageActionsDelegate) -> [MenuAction] {
class func mediaActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
var actions: [MenuAction] = []
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(replyAction)
if self.hasMediaActionContent {
let copyMediaAction = MessageActionBuilder.copyMedia(conversationViewItem: self, delegate: delegate)
if conversationViewItem.hasMediaActionContent {
let copyMediaAction = MessageActionBuilder.copyMedia(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(copyMediaAction)
if self.canSaveMedia() {
let saveMediaAction = MessageActionBuilder.saveMedia(conversationViewItem: self, delegate: delegate)
if conversationViewItem.canSaveMedia() {
let saveMediaAction = MessageActionBuilder.saveMedia(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(saveMediaAction)
}
}
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(deleteAction)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
actions.append(showDetailsAction)
return actions
}
@objc
func quotedMessageActions(delegate: MessageActionsDelegate) -> [MenuAction] {
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
class func quotedMessageActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
return [replyAction, deleteAction, showDetailsAction]
}
@objc
func infoMessageActions(delegate: MessageActionsDelegate) -> [MenuAction] {
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
class func infoMessageActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
return [deleteAction]
}

View File

@ -6,7 +6,6 @@ NS_ASSUME_NONNULL_BEGIN
@class ConversationStyle;
@class ConversationViewCell;
@class ConversationViewItem;
@class OWSContactOffersInteraction;
@class OWSContactsManager;
@class TSAttachmentPointer;
@ -19,13 +18,15 @@ NS_ASSUME_NONNULL_BEGIN
@class TSOutgoingMessage;
@class TSQuotedMessage;
@protocol ConversationViewItem;
@protocol ConversationViewCellDelegate <NSObject>
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(ConversationViewItem *)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(ConversationViewItem *)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(ConversationViewItem *)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(id<ConversationViewItem>)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(id<ConversationViewItem>)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(id<ConversationViewItem>)viewItem;
- (void)conversationCell:(ConversationViewCell *)cell
didLongpressSystemMessageViewItem:(ConversationViewItem *)viewItem;
didLongpressSystemMessageViewItem:(id<ConversationViewItem>)viewItem;
#pragma mark - System Cell
@ -68,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, nullable, weak) id<ConversationViewCellDelegate> delegate;
@property (nonatomic, nullable) ConversationViewItem *viewItem;
@property (nonatomic, nullable) id<ConversationViewItem> viewItem;
// Cells are prefetched but expensive cells (e.g. media) should only load
// when visible and unload when no longer visible. Non-visible cells can

View File

@ -7,14 +7,15 @@
NS_ASSUME_NONNULL_BEGIN
@class ConversationStyle;
@class ConversationViewItem;
@class TSAttachmentStream;
@protocol ConversationViewItem;
@interface OWSAudioMessageView : UIStackView
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
isIncoming:(BOOL)isIncoming
viewItem:(ConversationViewItem *)viewItem
viewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle;
- (void)createContents;

View File

@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) TSAttachmentStream *attachmentStream;
@property (nonatomic) BOOL isIncoming;
@property (nonatomic, weak) ConversationViewItem *viewItem;
@property (nonatomic, weak) id<ConversationViewItem> viewItem;
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
@property (nonatomic, nullable) UIButton *audioPlayPauseButton;
@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
isIncoming:(BOOL)isIncoming
viewItem:(ConversationViewItem *)viewItem
viewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle
{
self = [super init];

View File

@ -6,7 +6,9 @@ NS_ASSUME_NONNULL_BEGIN
@class ContactShareViewModel;
@class ConversationStyle;
@class ConversationViewItem;
@protocol ConversationViewItem;
@class OWSContact;
@class OWSQuotedReplyModel;
@class TSAttachmentPointer;
@ -25,27 +27,27 @@ extern const UIDataDetectorTypes kOWSAllowedDataDetectorTypes;
@protocol OWSMessageBubbleViewDelegate
- (void)didTapImageViewItem:(ConversationViewItem *)viewItem
- (void)didTapImageViewItem:(id<ConversationViewItem>)viewItem
attachmentStream:(TSAttachmentStream *)attachmentStream
imageView:(UIView *)imageView;
- (void)didTapVideoViewItem:(ConversationViewItem *)viewItem
- (void)didTapVideoViewItem:(id<ConversationViewItem>)viewItem
attachmentStream:(TSAttachmentStream *)attachmentStream
imageView:(UIView *)imageView;
- (void)didTapAudioViewItem:(ConversationViewItem *)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream;
- (void)didTapAudioViewItem:(id<ConversationViewItem>)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream;
- (void)didTapTruncatedTextMessage:(ConversationViewItem *)conversationItem;
- (void)didTapTruncatedTextMessage:(id<ConversationViewItem>)conversationItem;
- (void)didTapFailedIncomingAttachment:(ConversationViewItem *)viewItem
- (void)didTapFailedIncomingAttachment:(id<ConversationViewItem>)viewItem
attachmentPointer:(TSAttachmentPointer *)attachmentPointer;
- (void)didTapConversationItem:(ConversationViewItem *)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply;
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply;
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem
quotedReply:(OWSQuotedReplyModel *)quotedReply
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer;
- (void)didTapContactShareViewItem:(ConversationViewItem *)viewItem;
- (void)didTapContactShareViewItem:(id<ConversationViewItem>)viewItem;
- (void)didTapSendMessageToContactShare:(ContactShareViewModel *)contactShare
NS_SWIFT_NAME(didTapSendMessage(toContactShare:));
@ -60,7 +62,7 @@ extern const UIDataDetectorTypes kOWSAllowedDataDetectorTypes;
@interface OWSMessageBubbleView : UIView
@property (nonatomic, nullable) ConversationViewItem *viewItem;
@property (nonatomic, nullable) id<ConversationViewItem> viewItem;
@property (nonatomic) ConversationStyle *conversationStyle;

View File

@ -2,19 +2,20 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
@class ConversationStyle;
@class ConversationViewItem;
NS_ASSUME_NONNULL_BEGIN
@class ConversationStyle;
@protocol ConversationViewItem;
@interface OWSMessageFooterView : UIStackView
- (void)configureWithConversationViewItem:(ConversationViewItem *)viewItem
- (void)configureWithConversationViewItem:(id<ConversationViewItem>)viewItem
isOverlayingMedia:(BOOL)isOverlayingMedia
conversationStyle:(ConversationStyle *)conversationStyle
isIncoming:(BOOL)isIncoming;
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem;
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem;
- (void)prepareForReuse;

View File

@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Load
- (void)configureWithConversationViewItem:(ConversationViewItem *)viewItem
- (void)configureWithConversationViewItem:(id<ConversationViewItem>)viewItem
isOverlayingMedia:(BOOL)isOverlayingMedia
conversationStyle:(ConversationStyle *)conversationStyle
isIncoming:(BOOL)isIncoming
@ -186,7 +186,7 @@ NS_ASSUME_NONNULL_BEGIN
[self.statusIndicatorImageView.layer addAnimation:animation forKey:@"animation"];
}
- (BOOL)isFailedOutgoingMessage:(ConversationViewItem *)viewItem
- (BOOL)isFailedOutgoingMessage:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -200,7 +200,7 @@ NS_ASSUME_NONNULL_BEGIN
return messageStatus == MessageReceiptStatusFailed;
}
- (void)configureLabelsWithConversationViewItem:(ConversationViewItem *)viewItem
- (void)configureLabelsWithConversationViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -217,7 +217,7 @@ NS_ASSUME_NONNULL_BEGIN
self.timestampLabel.text = timestampLabelText.localizedUppercaseString;
}
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -243,7 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
return CGSizeCeil(result);
}
- (nullable NSString *)messageStatusTextForConversationViewItem:(ConversationViewItem *)viewItem
- (nullable NSString *)messageStatusTextForConversationViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
if (viewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage) {

View File

@ -5,16 +5,17 @@
extern const CGFloat OWSMessageHeaderViewDateHeaderVMargin;
@class ConversationStyle;
@class ConversationViewItem;
@protocol ConversationViewItem;
NS_ASSUME_NONNULL_BEGIN
@interface OWSMessageHeaderView : UIStackView
- (void)loadForDisplayWithViewItem:(ConversationViewItem *)viewItem
- (void)loadForDisplayWithViewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle;
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle;
@end

View File

@ -72,7 +72,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
[self addSubview:self.stackView];
}
- (void)loadForDisplayWithViewItem:(ConversationViewItem *)viewItem
- (void)loadForDisplayWithViewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle
{
OWSAssertDebug(viewItem);
@ -100,7 +100,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
];
}
- (CGFloat)strokeThicknessWithViewItem:(ConversationViewItem *)viewItem
- (CGFloat)strokeThicknessWithViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -111,7 +111,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
}
}
- (UIColor *)strokeColorWithViewItem:(ConversationViewItem *)viewItem
- (UIColor *)strokeColorWithViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -122,7 +122,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
}
}
- (void)configureLabelsWithViewItem:(ConversationViewItem *)viewItem
- (void)configureLabelsWithViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertDebug(viewItem);
@ -158,7 +158,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
}
}
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
conversationStyle:(ConversationStyle *)conversationStyle
{
OWSAssertDebug(viewItem);

View File

@ -175,8 +175,8 @@ typedef enum : NSUInteger {
@property (nonatomic, readonly) ConversationViewLayout *layout;
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
@property (nonatomic) NSArray<ConversationViewItem *> *viewItems;
@property (nonatomic) NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache;
@property (nonatomic) NSArray<id<ConversationViewItem>> *viewItems;
@property (nonatomic) NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache;
@property (nonatomic, nullable) AVAudioRecorder *audioRecorder;
@property (nonatomic, nullable) OWSAudioPlayer *audioAttachmentPlayer;
@ -717,7 +717,7 @@ typedef enum : NSUInteger {
- (NSIndexPath *_Nullable)indexPathOfUnreadMessagesIndicator
{
NSInteger row = 0;
for (ConversationViewItem *viewItem in self.viewItems) {
for (id<ConversationViewItem> viewItem in self.viewItems) {
if (viewItem.unreadIndicator) {
return [NSIndexPath indexPathForRow:row inSection:0];
}
@ -1553,7 +1553,7 @@ typedef enum : NSUInteger {
OWSLogInfo(@"didChangePreferredContentSize");
// Evacuate cached cell sizes.
for (ConversationViewItem *viewItem in self.viewItems) {
for (id<ConversationViewItem> viewItem in self.viewItems) {
[viewItem clearCachedLayoutState];
}
[self resetContentAndLayout];
@ -1933,12 +1933,12 @@ typedef enum : NSUInteger {
#pragma mark - MessageActionsDelegate
- (void)messageActionsShowDetailsForItem:(ConversationViewItem *)conversationViewItem
- (void)messageActionsShowDetailsForItem:(id<ConversationViewItem>)conversationViewItem
{
[self showDetailViewForViewItem:conversationViewItem];
}
- (void)messageActionsReplyToItem:(ConversationViewItem *)conversationViewItem
- (void)messageActionsReplyToItem:(id<ConversationViewItem>)conversationViewItem
{
[self populateReplyForViewItem:conversationViewItem];
}
@ -2006,27 +2006,32 @@ typedef enum : NSUInteger {
#pragma mark - ConversationViewCellDelegate
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(ConversationViewItem *)viewItem
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(id<ConversationViewItem>)viewItem
{
NSArray<MenuAction *> *messageActions = [viewItem mediaActionsWithDelegate:self];
NSArray<MenuAction *> *messageActions =
[ConversationViewItemActions mediaActionsWithConversationViewItem:viewItem delegate:self];
[self presentMessageActions:messageActions withFocusedCell:cell];
}
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(ConversationViewItem *)viewItem
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(id<ConversationViewItem>)viewItem
{
NSArray<MenuAction *> *messageActions = [viewItem textActionsWithDelegate:self];
NSArray<MenuAction *> *messageActions =
[ConversationViewItemActions textActionsWithConversationViewItem:viewItem delegate:self];
[self presentMessageActions:messageActions withFocusedCell:cell];
}
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(ConversationViewItem *)viewItem
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(id<ConversationViewItem>)viewItem
{
NSArray<MenuAction *> *messageActions = [viewItem quotedMessageActionsWithDelegate:self];
NSArray<MenuAction *> *messageActions =
[ConversationViewItemActions quotedMessageActionsWithConversationViewItem:viewItem delegate:self];
[self presentMessageActions:messageActions withFocusedCell:cell];
}
- (void)conversationCell:(ConversationViewCell *)cell didLongpressSystemMessageViewItem:(ConversationViewItem *)viewItem
- (void)conversationCell:(ConversationViewCell *)cell
didLongpressSystemMessageViewItem:(id<ConversationViewItem>)viewItem
{
NSArray<MenuAction *> *messageActions = [viewItem infoMessageActionsWithDelegate:self];
NSArray<MenuAction *> *messageActions =
[ConversationViewItemActions infoMessageActionsWithConversationViewItem:viewItem delegate:self];
[self presentMessageActions:messageActions withFocusedCell:cell];
}
@ -2141,7 +2146,7 @@ typedef enum : NSUInteger {
#pragma mark - OWSMessageBubbleViewDelegate
- (void)didTapImageViewItem:(ConversationViewItem *)viewItem
- (void)didTapImageViewItem:(id<ConversationViewItem>)viewItem
attachmentStream:(TSAttachmentStream *)attachmentStream
imageView:(UIView *)imageView
{
@ -2172,7 +2177,7 @@ typedef enum : NSUInteger {
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
}
- (void)didTapVideoViewItem:(ConversationViewItem *)viewItem
- (void)didTapVideoViewItem:(id<ConversationViewItem>)viewItem
attachmentStream:(TSAttachmentStream *)attachmentStream
imageView:(UIImageView *)imageView
{
@ -2201,7 +2206,7 @@ typedef enum : NSUInteger {
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
}
- (void)didTapAudioViewItem:(ConversationViewItem *)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream
- (void)didTapAudioViewItem:(id<ConversationViewItem>)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream
{
OWSAssertIsOnMainThread();
OWSAssertDebug(viewItem);
@ -2231,7 +2236,7 @@ typedef enum : NSUInteger {
[self.audioAttachmentPlayer playWithPlaybackAudioCategory];
}
- (void)didTapTruncatedTextMessage:(ConversationViewItem *)conversationItem
- (void)didTapTruncatedTextMessage:(id<ConversationViewItem>)conversationItem
{
OWSAssertIsOnMainThread();
OWSAssertDebug(conversationItem);
@ -2241,7 +2246,7 @@ typedef enum : NSUInteger {
[self.navigationController pushViewController:view animated:YES];
}
- (void)didTapContactShareViewItem:(ConversationViewItem *)conversationItem
- (void)didTapContactShareViewItem:(id<ConversationViewItem>)conversationItem
{
OWSAssertIsOnMainThread();
OWSAssertDebug(conversationItem);
@ -2276,7 +2281,7 @@ typedef enum : NSUInteger {
[self.contactShareViewHelper showAddToContactsWithContactShare:contactShare fromViewController:self];
}
- (void)didTapFailedIncomingAttachment:(ConversationViewItem *)viewItem
- (void)didTapFailedIncomingAttachment:(id<ConversationViewItem>)viewItem
attachmentPointer:(TSAttachmentPointer *)attachmentPointer
{
OWSAssertIsOnMainThread();
@ -2296,7 +2301,7 @@ typedef enum : NSUInteger {
[self handleUnsentMessageTap:message];
}
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem
quotedReply:(OWSQuotedReplyModel *)quotedReply
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer
{
@ -2334,7 +2339,7 @@ typedef enum : NSUInteger {
}];
}
- (void)didTapConversationItem:(ConversationViewItem *)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply
{
OWSAssertIsOnMainThread();
OWSAssertDebug(viewItem);
@ -2469,7 +2474,7 @@ typedef enum : NSUInteger {
return @(groupIndex);
}
- (void)showDetailViewForViewItem:(ConversationViewItem *)conversationItem
- (void)showDetailViewForViewItem:(id<ConversationViewItem>)conversationItem
{
OWSAssertIsOnMainThread();
OWSAssertDebug(conversationItem);
@ -2484,7 +2489,7 @@ typedef enum : NSUInteger {
[self.navigationController pushViewController:view animated:YES];
}
- (void)populateReplyForViewItem:(ConversationViewItem *)conversationItem
- (void)populateReplyForViewItem:(id<ConversationViewItem>)conversationItem
{
OWSLogDebug(@"user did tap reply");
@ -2559,7 +2564,7 @@ typedef enum : NSUInteger {
NSIndexPath *_Nullable indexPathOfUnreadIndicator = [self indexPathOfUnreadMessagesIndicator];
if (indexPathOfUnreadIndicator) {
ConversationViewItem *oldIndicatorItem = [self viewItemForIndex:indexPathOfUnreadIndicator.row];
id<ConversationViewItem> oldIndicatorItem = [self viewItemForIndex:indexPathOfUnreadIndicator.row];
OWSAssertDebug(oldIndicatorItem);
// TODO ideally this would be happening within the *same* transaction that caused the unreadMessageIndicator
@ -2673,7 +2678,7 @@ typedef enum : NSUInteger {
BOOL isScrolledUp = scrollSpaceToBottom > pageHeight * 1.f;
if (self.viewItems.count > 0) {
ConversationViewItem *lastViewItem = [self.viewItems lastObject];
id<ConversationViewItem> lastViewItem = [self.viewItems lastObject];
OWSAssertDebug(lastViewItem);
if (lastViewItem.interaction.timestampForSorting > self.lastVisibleTimestamp) {
@ -3289,7 +3294,7 @@ typedef enum : NSUInteger {
case YapDatabaseViewChangeUpdate: {
YapCollectionKey *collectionKey = rowChange.collectionKey;
if (collectionKey.key) {
ConversationViewItem *_Nullable viewItem = self.viewItemCache[collectionKey.key];
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[collectionKey.key];
if (viewItem) {
[self reloadInteractionForViewItem:viewItem];
} else {
@ -3373,7 +3378,8 @@ typedef enum : NSUInteger {
(unsigned long)rowChange.finalIndex);
[self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]];
ConversationViewItem *_Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
id<ConversationViewItem> _Nullable viewItem =
[self viewItemForIndex:(NSInteger)rowChange.finalIndex];
if ([viewItem.interaction isKindOfClass:[TSOutgoingMessage class]]) {
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction;
if (!outgoingMessage.isFromLinkedDevice) {
@ -3508,7 +3514,7 @@ typedef enum : NSUInteger {
isOnlyModifyingLastMessage = NO;
break;
case YapDatabaseViewChangeInsert: {
ConversationViewItem *_Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
id<ConversationViewItem> _Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
if (([viewItem.interaction isKindOfClass:[TSIncomingMessage class]] ||
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
&& rowChange.finalIndex >= oldViewItemCount) {
@ -3524,7 +3530,7 @@ typedef enum : NSUInteger {
if (rowChange.changes == YapDatabaseViewChangedDependency) {
continue;
}
ConversationViewItem *_Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
id<ConversationViewItem> _Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
if (([viewItem.interaction isKindOfClass:[TSIncomingMessage class]] ||
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
&& rowChange.finalIndex >= oldViewItemCount) {
@ -3855,7 +3861,7 @@ typedef enum : NSUInteger {
return lastVisibleIndexPath;
}
- (nullable ConversationViewItem *)lastVisibleViewItem
- (nullable id<ConversationViewItem>)lastVisibleViewItem
{
NSIndexPath *_Nullable lastVisibleIndexPath = [self lastVisibleIndexPath];
if (!lastVisibleIndexPath) {
@ -3870,7 +3876,7 @@ typedef enum : NSUInteger {
- (void)didScrollToBottom
{
ConversationViewItem *_Nullable lastVisibleViewItem = [self.viewItems lastObject];
id<ConversationViewItem> _Nullable lastVisibleViewItem = [self.viewItems lastObject];
if (lastVisibleViewItem) {
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
@ -3883,7 +3889,7 @@ typedef enum : NSUInteger {
- (void)updateLastVisibleTimestamp
{
ConversationViewItem *_Nullable lastVisibleViewItem = [self lastVisibleViewItem];
id<ConversationViewItem> _Nullable lastVisibleViewItem = [self lastVisibleViewItem];
if (lastVisibleViewItem) {
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
@ -4640,7 +4646,7 @@ typedef enum : NSUInteger {
// any new items inserted while we were not observing. We therefore find the
// first item at or after the "view horizon". See the comments below which explain
// the "view horizon".
ConversationViewItem *_Nullable lastViewItem = self.viewItems.lastObject;
id<ConversationViewItem> _Nullable lastViewItem = self.viewItems.lastObject;
BOOL hasAddedNewItems = (lastViewItem && previousLastTimestamp
&& lastViewItem.interaction.timestamp > previousLastTimestamp.unsignedLongLongValue);
@ -4671,7 +4677,7 @@ typedef enum : NSUInteger {
// We'll use this later to update the view to reflect any changes made while
// we were not observing the database. See extendRangeToIncludeUnobservedItems
// and the logic above.
ConversationViewItem *_Nullable lastViewItem = self.viewItems.lastObject;
id<ConversationViewItem> _Nullable lastViewItem = self.viewItems.lastObject;
if (lastViewItem) {
self.previousLastTimestamp = @(lastViewItem.interaction.timestamp);
} else {
@ -4717,7 +4723,7 @@ typedef enum : NSUInteger {
NSUInteger mid = (left + right) / 2;
OWSAssertDebug(left <= mid);
OWSAssertDebug(mid < right);
ConversationViewItem *viewItem = self.viewItems[mid];
id<ConversationViewItem> viewItem = self.viewItems[mid];
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
right = mid;
} else {
@ -4726,7 +4732,7 @@ typedef enum : NSUInteger {
}
}
OWSAssertDebug(left == right);
ConversationViewItem *viewItem = self.viewItems[left];
id<ConversationViewItem> viewItem = self.viewItems[left];
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
OWSLogInfo(@"firstIndexPathAtViewHorizonTimestamp: %zd / %zd", left, self.viewItems.count);
return [NSIndexPath indexPathForRow:(NSInteger) left inSection:0];
@ -4860,8 +4866,8 @@ typedef enum : NSUInteger {
// Returns NO on error.
- (BOOL)reloadViewItems
{
NSMutableArray<ConversationViewItem *> *viewItems = [NSMutableArray new];
NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache = [NSMutableDictionary new];
NSMutableArray<id<ConversationViewItem>> *viewItems = [NSMutableArray new];
NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache = [NSMutableDictionary new];
NSUInteger count = [self.messageMappings numberOfItemsInSection:0];
BOOL isGroupThread = self.isGroupConversation;
@ -4890,12 +4896,12 @@ typedef enum : NSUInteger {
continue;
}
ConversationViewItem *_Nullable viewItem = self.viewItemCache[interaction.uniqueId];
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId];
if (!viewItem) {
viewItem = [[ConversationViewItem alloc] initWithInteraction:interaction
isGroupThread:isGroupThread
transaction:transaction
conversationStyle:self.conversationStyle];
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
isGroupThread:isGroupThread
transaction:transaction
conversationStyle:self.conversationStyle];
}
[viewItems addObject:viewItem];
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
@ -4916,7 +4922,7 @@ typedef enum : NSUInteger {
uint64_t collapseCutoffTimestamp = [NSDate ows_millisecondsSince1970ForDate:self.collapseCutoffDate];
BOOL hasPlacedUnreadIndicator = NO;
for (ConversationViewItem *viewItem in viewItems) {
for (id<ConversationViewItem> viewItem in viewItems) {
BOOL canShowDate = NO;
switch (viewItem.interaction.interactionType) {
case OWSInteractionType_Unknown:
@ -4992,9 +4998,9 @@ typedef enum : NSUInteger {
//
// NOTE: This logic uses the break properties which are set in the previous pass.
for (NSUInteger i = 0; i < viewItems.count; i++) {
ConversationViewItem *viewItem = viewItems[i];
ConversationViewItem *_Nullable previousViewItem = (i > 0 ? viewItems[i - 1] : nil);
ConversationViewItem *_Nullable nextViewItem = (i + 1 < viewItems.count ? viewItems[i + 1] : nil);
id<ConversationViewItem> viewItem = viewItems[i];
id<ConversationViewItem> _Nullable previousViewItem = (i > 0 ? viewItems[i - 1] : nil);
id<ConversationViewItem> _Nullable nextViewItem = (i + 1 < viewItems.count ? viewItems[i + 1] : nil);
BOOL shouldShowSenderAvatar = NO;
BOOL shouldHideFooter = NO;
BOOL isFirstInCluster = YES;
@ -5143,7 +5149,7 @@ typedef enum : NSUInteger {
// Whenever an interaction is modified, we need to reload it from the DB
// and update the corresponding view item.
- (void)reloadInteractionForViewItem:(ConversationViewItem *)viewItem
- (void)reloadInteractionForViewItem:(id<ConversationViewItem>)viewItem
{
OWSAssertIsOnMainThread();
OWSAssertDebug(viewItem);
@ -5164,7 +5170,7 @@ typedef enum : NSUInteger {
}];
}
- (nullable ConversationViewItem *)viewItemForIndex:(NSInteger)index
- (nullable id<ConversationViewItem>)viewItemForIndex:(NSInteger)index
{
if (index < 0 || index >= (NSInteger)self.viewItems.count) {
OWSFailDebug(@"Invalid view item index: %lu", (unsigned long)index);
@ -5183,7 +5189,7 @@ typedef enum : NSUInteger {
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ConversationViewItem *_Nullable viewItem = [self viewItemForIndex:indexPath.row];
id<ConversationViewItem> _Nullable viewItem = [self viewItemForIndex:indexPath.row];
ConversationViewCell *cell = [viewItem dequeueCellForCollectionView:self.collectionView indexPath:indexPath];
if (!cell) {
OWSFailDebug(@"Could not dequeue cell.");

View File

@ -43,7 +43,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
//
// Critically, this class implements ConversationViewLayoutItem
// and does caching of the cell's size.
@interface ConversationViewItem : NSObject <ConversationViewLayoutItem, OWSAudioPlayerDelegate>
@protocol ConversationViewItem <NSObject, ConversationViewLayoutItem, OWSAudioPlayerDelegate>
@property (nonatomic, readonly) TSInteraction *interaction;
@ -69,14 +69,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@property (nonatomic, nullable) OWSUnreadIndicator *unreadIndicator;
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithInteraction:(TSInteraction *)interaction
isGroupThread:(BOOL)isGroupThread
transaction:(YapDatabaseReadTransaction *)transaction
conversationStyle:(ConversationStyle *)conversationStyle;
- (ConversationViewCell *)dequeueCellForCollectionView:(UICollectionView *)collectionView
indexPath:(NSIndexPath *)indexPath;
@ -89,21 +81,20 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView;
@property (nonatomic, readonly) CGFloat audioDurationSeconds;
- (CGFloat)audioProgressSeconds;
@property (nonatomic, readonly) CGFloat audioProgressSeconds;
#pragma mark - View State Caching
// These methods only apply to text & attachment messages.
- (OWSMessageCellType)messageCellType;
- (nullable DisplayableText *)displayableBodyText;
- (nullable TSAttachmentStream *)attachmentStream;
- (nullable TSAttachmentPointer *)attachmentPointer;
- (CGSize)mediaSize;
@property (nonatomic, readonly) OWSMessageCellType messageCellType;
@property (nonatomic, readonly, nullable) DisplayableText *displayableBodyText;
@property (nonatomic, readonly, nullable) TSAttachmentStream *attachmentStream;
@property (nonatomic, readonly, nullable) TSAttachmentPointer *attachmentPointer;
@property (nonatomic, readonly) CGSize mediaSize;
- (nullable DisplayableText *)displayableQuotedText;
- (nullable NSString *)quotedAttachmentMimetype;
- (nullable NSString *)quotedRecipientId;
@property (nonatomic, readonly, nullable) DisplayableText *displayableQuotedText;
@property (nonatomic, readonly, nullable) NSString *quotedAttachmentMimetype;
@property (nonatomic, readonly, nullable) NSString *quotedRecipientId;
// We don't want to try to load the media for this item (if any)
// if a load has previously failed.
@ -132,4 +123,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
@end
@interface ConversationInteractionViewItem
: NSObject <ConversationViewItem, ConversationViewLayoutItem, OWSAudioPlayerDelegate>
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithInteraction:(TSInteraction *)interaction
isGroupThread:(BOOL)isGroupThread
transaction:(YapDatabaseReadTransaction *)transaction
conversationStyle:(ConversationStyle *)conversationStyle;
@end
NS_ASSUME_NONNULL_END

View File

@ -46,7 +46,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
#pragma mark -
@interface ConversationViewItem ()
@interface ConversationInteractionViewItem ()
@property (nonatomic, nullable) NSValue *cachedCellSize;
@ -70,12 +70,25 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
@property (nonatomic, nullable) NSString *systemMessageText;
@property (nonatomic, nullable) TSThread *incomingMessageAuthorThread;
@property (nonatomic, nullable) NSString *authorConversationColorName;
@property (nonatomic, nullable) ConversationStyle *conversationStyle;
@end
#pragma mark -
@implementation ConversationViewItem
@implementation ConversationInteractionViewItem
@synthesize shouldShowDate = _shouldShowDate;
@synthesize shouldShowSenderAvatar = _shouldShowSenderAvatar;
@synthesize unreadIndicator = _unreadIndicator;
@synthesize didCellMediaFailToLoad = _didCellMediaFailToLoad;
@synthesize interaction = _interaction;
@synthesize isFirstInCluster = _isFirstInCluster;
@synthesize isGroupThread = _isGroupThread;
@synthesize isLastInCluster = _isLastInCluster;
@synthesize lastAudioMessageView = _lastAudioMessageView;
@synthesize senderName = _senderName;
@synthesize shouldHideFooter = _shouldHideFooter;
- (instancetype)initWithInteraction:(TSInteraction *)interaction
isGroupThread:(BOOL)isGroupThread
@ -293,7 +306,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
return measurementCell;
}
- (CGFloat)vSpacingWithPreviousLayoutItem:(ConversationViewItem *)previousLayoutItem
- (CGFloat)vSpacingWithPreviousLayoutItem:(id<ConversationViewItem>)previousLayoutItem
{
OWSAssertDebug(previousLayoutItem);

View File

@ -1967,10 +1967,11 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(messageToQuote);
OWSLogVerbose(@"%@", label);
[DDLog flushLog];
ConversationViewItem *viewItem = [[ConversationViewItem alloc] initWithInteraction:messageToQuote
isGroupThread:thread.isGroupThread
transaction:transaction
conversationStyle:conversationStyle];
id<ConversationViewItem> viewItem =
[[ConversationInteractionViewItem alloc] initWithInteraction:messageToQuote
isGroupThread:thread.isGroupThread
transaction:transaction
conversationStyle:conversationStyle];
quotedMessage = [
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
buildQuotedMessageForSending];
@ -1986,10 +1987,11 @@ NS_ASSUME_NONNULL_BEGIN
transaction:transaction];
OWSAssertDebug(messageToQuote);
ConversationViewItem *viewItem = [[ConversationViewItem alloc] initWithInteraction:messageToQuote
isGroupThread:thread.isGroupThread
transaction:transaction
conversationStyle:conversationStyle];
id<ConversationViewItem> viewItem =
[[ConversationInteractionViewItem alloc] initWithInteraction:messageToQuote
isGroupThread:thread.isGroupThread
transaction:transaction
conversationStyle:conversationStyle];
quotedMessage = [
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
buildQuotedMessageForSending];

View File

@ -37,7 +37,7 @@ public class LongTextViewController: OWSViewController {
guard viewItem.hasBodyText else {
return ""
}
guard let displayableText = viewItem.displayableBodyText() else {
guard let displayableText = viewItem.displayableBodyText else {
return ""
}
let messageBody = displayableText.fullText

View File

@ -6,7 +6,8 @@
NS_ASSUME_NONNULL_BEGIN
@class ConversationViewItem;
@protocol ConversationViewItem;
@class GalleryItemBox;
@class MediaDetailViewController;
@ -18,7 +19,7 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
@protocol MediaDetailViewControllerDelegate <NSObject>
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
requestDeleteConversationViewItem:(ConversationViewItem *)conversationViewItem;
requestDeleteConversationViewItem:(id<ConversationViewItem>)conversationViewItem;
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
isPlayingVideo:(BOOL)isPlayingVideo;
@ -34,7 +35,7 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
// If viewItem is non-null, long press will show a menu controller.
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
viewItem:(ConversationViewItem *_Nullable)viewItem;
viewItem:(nullable id<ConversationViewItem>)viewItem;
#pragma mark - Actions
- (void)didPressShare:(id)sender;

View File

@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) UIButton *shareButton;
@property (nonatomic) TSAttachmentStream *attachmentStream;
@property (nonatomic, nullable) ConversationViewItem *viewItem;
@property (nonatomic, nullable) id<ConversationViewItem> viewItem;
@property (nonatomic, nullable) UIImage *image;
@property (nonatomic, nullable) OWSVideoPlayer *videoPlayer;
@ -63,7 +63,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
viewItem:(ConversationViewItem *_Nullable)viewItem
viewItem:(nullable id<ConversationViewItem>)viewItem
{
self = [super initWithNibName:nil bundle:nil];
if (!self) {

View File

@ -479,10 +479,10 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
let message = galleryItem.message
let thread = message.thread(with: transaction)
let conversationStyle = ConversationStyle(thread: thread)
fetchedItem = ConversationViewItem(interaction: message,
isGroupThread: thread.isGroupThread(),
transaction: transaction,
conversationStyle: conversationStyle)
fetchedItem = ConversationInteractionViewItem(interaction: message,
isGroupThread: thread.isGroupThread(),
transaction: transaction,
conversationStyle: conversationStyle)
}
guard let viewItem = fetchedItem else {

View File

@ -326,7 +326,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
guard viewItem.hasBodyText else {
return nil
}
guard let displayableText = viewItem.displayableBodyText() else {
guard let displayableText = viewItem.displayableBodyText else {
return nil
}
let messageBody = displayableText.fullText
@ -663,7 +663,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
if let audioAttachmentPlayer = self.audioAttachmentPlayer {
// Is this player associated with this media adapter?
if audioAttachmentPlayer.owner as? ConversationViewItem == viewItem {
if audioAttachmentPlayer.owner === viewItem {
// Tap to pause & unpause.
audioAttachmentPlayer.togglePlayState()
return

View File

@ -39,22 +39,22 @@
return @"abc";
}
- (ConversationViewItem *)textViewItem
- (ConversationInteractionViewItem *)textViewItem
{
TSOutgoingMessage *message =
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:self.fakeTextMessageText attachmentId:nil];
[message save];
__block ConversationViewItem *viewItem = nil;
__block ConversationInteractionViewItem *viewItem = nil;
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
viewItem = [[ConversationViewItem alloc] initWithInteraction:message
isGroupThread:NO
transaction:transaction
conversationStyle:self.conversationStyle];
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:message
isGroupThread:NO
transaction:transaction
conversationStyle:self.conversationStyle];
}];
return viewItem;
}
- (ConversationViewItem *)viewItemWithAttachmentMimetype:(NSString *)mimeType filename:(NSString *)filename
- (ConversationInteractionViewItem *)viewItemWithAttachmentMimetype:(NSString *)mimeType filename:(NSString *)filename
{
OWSAssertDebug(filename.length > 0);
@ -74,33 +74,33 @@
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:nil attachmentId:attachment.uniqueId];
[message save];
__block ConversationViewItem *viewItem = nil;
__block ConversationInteractionViewItem *viewItem = nil;
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
viewItem = [[ConversationViewItem alloc] initWithInteraction:message
isGroupThread:NO
transaction:transaction
conversationStyle:self.conversationStyle];
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:message
isGroupThread:NO
transaction:transaction
conversationStyle:self.conversationStyle];
}];
return viewItem;
}
- (ConversationViewItem *)stillImageViewItem
- (ConversationInteractionViewItem *)stillImageViewItem
{
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageJpeg filename:@"test-jpg.jpg"];
}
- (ConversationViewItem *)animatedImageViewItem
- (ConversationInteractionViewItem *)animatedImageViewItem
{
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageGif filename:@"test-gif.gif"];
}
- (ConversationViewItem *)videoViewItem
- (ConversationInteractionViewItem *)videoViewItem
{
return [self viewItemWithAttachmentMimetype:@"video/mp4" filename:@"test-mp4.mp4"];
}
- (ConversationViewItem *)audioViewItem
- (ConversationInteractionViewItem *)audioViewItem
{
return [self viewItemWithAttachmentMimetype:@"audio/mp3" filename:@"test-mp3.mp3"];
}
@ -109,7 +109,7 @@
- (void)testPerformDeleteEditingActionWithNonMediaMessage
{
ConversationViewItem *viewItem = self.textViewItem;
ConversationInteractionViewItem *viewItem = self.textViewItem;
XCTAssertNotNil([TSMessage fetchObjectWithUniqueID:viewItem.interaction.uniqueId]);
[viewItem deleteAction];
@ -118,7 +118,7 @@
- (void)testPerformDeleteActionWithPhotoMessage
{
ConversationViewItem *viewItem = self.stillImageViewItem;
ConversationInteractionViewItem *viewItem = self.stillImageViewItem;
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
@ -140,7 +140,7 @@
- (void)testPerformDeleteEditingActionWithAnimatedMessage
{
ConversationViewItem *viewItem = self.animatedImageViewItem;
ConversationInteractionViewItem *viewItem = self.animatedImageViewItem;
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
@ -162,7 +162,7 @@
- (void)testPerformDeleteEditingActionWithVideoMessage
{
ConversationViewItem *viewItem = self.videoViewItem;
ConversationInteractionViewItem *viewItem = self.videoViewItem;
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
@ -184,7 +184,7 @@
- (void)testPerformDeleteEditingActionWithAudioMessage
{
ConversationViewItem *viewItem = self.audioViewItem;
ConversationInteractionViewItem *viewItem = self.audioViewItem;
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
@ -212,7 +212,7 @@
UIPasteboard.generalPasteboard.items = @[];
XCTAssertNil(UIPasteboard.generalPasteboard.string);
ConversationViewItem *viewItem = self.textViewItem;
ConversationInteractionViewItem *viewItem = self.textViewItem;
[viewItem copyTextAction];
XCTAssertEqualObjects(self.fakeTextMessageText, UIPasteboard.generalPasteboard.string);
}
@ -224,7 +224,7 @@
XCTAssertNil(UIPasteboard.generalPasteboard.image);
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG]);
ConversationViewItem *viewItem = self.stillImageViewItem;
ConversationInteractionViewItem *viewItem = self.stillImageViewItem;
[viewItem copyMediaAction];
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG];
XCTAssertTrue(copiedData.length > 0);
@ -237,7 +237,7 @@
XCTAssertNil(UIPasteboard.generalPasteboard.image);
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF]);
ConversationViewItem *viewItem = self.animatedImageViewItem;
ConversationInteractionViewItem *viewItem = self.animatedImageViewItem;
[viewItem copyMediaAction];
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF];
XCTAssertTrue(copiedData.length > 0);
@ -249,7 +249,7 @@
UIPasteboard.generalPasteboard.items = @[];
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4]);
ConversationViewItem *viewItem = self.videoViewItem;
ConversationInteractionViewItem *viewItem = self.videoViewItem;
[viewItem copyMediaAction];
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4];
XCTAssertTrue(copiedData.length > 0);
@ -261,7 +261,7 @@
UIPasteboard.generalPasteboard.items = @[];
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3]);
ConversationViewItem *viewItem = self.audioViewItem;
ConversationInteractionViewItem *viewItem = self.audioViewItem;
[viewItem copyMediaAction];
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3];
XCTAssertTrue(copiedData.length > 0);

View File

@ -6,7 +6,8 @@
NS_ASSUME_NONNULL_BEGIN
@class ConversationViewItem;
@protocol ConversationViewItem;
@class TSAttachmentPointer;
@class TSAttachmentStream;
@class TSMessage;
@ -42,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
transaction:(YapDatabaseReadTransaction *)transaction;
// Builds a not-yet-sent QuotedReplyModel
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(ConversationViewItem *)conversationItem
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(id<ConversationViewItem>)conversationItem
transaction:(YapDatabaseReadTransaction *)transaction;
- (TSQuotedMessage *)buildQuotedMessageForSending;

View File

@ -115,7 +115,7 @@ NS_ASSUME_NONNULL_BEGIN
thumbnailDownloadFailed:thumbnailDownloadFailed];
}
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(ConversationViewItem *)conversationItem
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(id<ConversationViewItem>)conversationItem
transaction:(YapDatabaseReadTransaction *)transaction;
{
OWSAssertDebug(conversationItem);