ConversationViewItem -> protocol
This commit is contained in:
parent
f56ac96d31
commit
06eae47e09
|
@ -67,66 +67,67 @@ struct MessageActionBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConversationViewItem {
|
@objc
|
||||||
|
class ConversationViewItemActions: NSObject {
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func textActions(delegate: MessageActionsDelegate) -> [MenuAction] {
|
class func textActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
|
||||||
var actions: [MenuAction] = []
|
var actions: [MenuAction] = []
|
||||||
|
|
||||||
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
|
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(replyAction)
|
actions.append(replyAction)
|
||||||
|
|
||||||
if self.hasBodyTextActionContent {
|
if conversationViewItem.hasBodyTextActionContent {
|
||||||
let copyTextAction = MessageActionBuilder.copyText(conversationViewItem: self, delegate: delegate)
|
let copyTextAction = MessageActionBuilder.copyText(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(copyTextAction)
|
actions.append(copyTextAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
|
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(deleteAction)
|
actions.append(deleteAction)
|
||||||
|
|
||||||
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
|
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(showDetailsAction)
|
actions.append(showDetailsAction)
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func mediaActions(delegate: MessageActionsDelegate) -> [MenuAction] {
|
class func mediaActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
|
||||||
var actions: [MenuAction] = []
|
var actions: [MenuAction] = []
|
||||||
|
|
||||||
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
|
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(replyAction)
|
actions.append(replyAction)
|
||||||
|
|
||||||
if self.hasMediaActionContent {
|
if conversationViewItem.hasMediaActionContent {
|
||||||
let copyMediaAction = MessageActionBuilder.copyMedia(conversationViewItem: self, delegate: delegate)
|
let copyMediaAction = MessageActionBuilder.copyMedia(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(copyMediaAction)
|
actions.append(copyMediaAction)
|
||||||
if self.canSaveMedia() {
|
if conversationViewItem.canSaveMedia() {
|
||||||
let saveMediaAction = MessageActionBuilder.saveMedia(conversationViewItem: self, delegate: delegate)
|
let saveMediaAction = MessageActionBuilder.saveMedia(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(saveMediaAction)
|
actions.append(saveMediaAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
|
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(deleteAction)
|
actions.append(deleteAction)
|
||||||
|
|
||||||
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
|
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
actions.append(showDetailsAction)
|
actions.append(showDetailsAction)
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func quotedMessageActions(delegate: MessageActionsDelegate) -> [MenuAction] {
|
class func quotedMessageActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
|
||||||
let replyAction = MessageActionBuilder.reply(conversationViewItem: self, delegate: delegate)
|
let replyAction = MessageActionBuilder.reply(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
|
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: self, delegate: delegate)
|
let showDetailsAction = MessageActionBuilder.showDetails(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
|
|
||||||
return [replyAction, deleteAction, showDetailsAction]
|
return [replyAction, deleteAction, showDetailsAction]
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func infoMessageActions(delegate: MessageActionsDelegate) -> [MenuAction] {
|
class func infoMessageActions(conversationViewItem: ConversationViewItem, delegate: MessageActionsDelegate) -> [MenuAction] {
|
||||||
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: self, delegate: delegate)
|
let deleteAction = MessageActionBuilder.deleteMessage(conversationViewItem: conversationViewItem, delegate: delegate)
|
||||||
|
|
||||||
return [deleteAction]
|
return [deleteAction]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ConversationStyle;
|
@class ConversationStyle;
|
||||||
@class ConversationViewCell;
|
@class ConversationViewCell;
|
||||||
@class ConversationViewItem;
|
|
||||||
@class OWSContactOffersInteraction;
|
@class OWSContactOffersInteraction;
|
||||||
@class OWSContactsManager;
|
@class OWSContactsManager;
|
||||||
@class TSAttachmentPointer;
|
@class TSAttachmentPointer;
|
||||||
|
@ -19,13 +18,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
@class TSOutgoingMessage;
|
@class TSOutgoingMessage;
|
||||||
@class TSQuotedMessage;
|
@class TSQuotedMessage;
|
||||||
|
|
||||||
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@protocol ConversationViewCellDelegate <NSObject>
|
@protocol ConversationViewCellDelegate <NSObject>
|
||||||
|
|
||||||
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(ConversationViewItem *)viewItem;
|
- (void)conversationCell:(ConversationViewCell *)cell didLongpressTextViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(ConversationViewItem *)viewItem;
|
- (void)conversationCell:(ConversationViewCell *)cell didLongpressMediaViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(ConversationViewItem *)viewItem;
|
- (void)conversationCell:(ConversationViewCell *)cell didLongpressQuoteViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
- (void)conversationCell:(ConversationViewCell *)cell
|
- (void)conversationCell:(ConversationViewCell *)cell
|
||||||
didLongpressSystemMessageViewItem:(ConversationViewItem *)viewItem;
|
didLongpressSystemMessageViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
|
|
||||||
#pragma mark - System Cell
|
#pragma mark - System Cell
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@property (nonatomic, nullable, weak) id<ConversationViewCellDelegate> delegate;
|
@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
|
// Cells are prefetched but expensive cells (e.g. media) should only load
|
||||||
// when visible and unload when no longer visible. Non-visible cells can
|
// when visible and unload when no longer visible. Non-visible cells can
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ConversationStyle;
|
@class ConversationStyle;
|
||||||
@class ConversationViewItem;
|
|
||||||
@class TSAttachmentStream;
|
@class TSAttachmentStream;
|
||||||
|
|
||||||
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@interface OWSAudioMessageView : UIStackView
|
@interface OWSAudioMessageView : UIStackView
|
||||||
|
|
||||||
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
|
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
|
||||||
isIncoming:(BOOL)isIncoming
|
isIncoming:(BOOL)isIncoming
|
||||||
viewItem:(ConversationViewItem *)viewItem
|
viewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle;
|
conversationStyle:(ConversationStyle *)conversationStyle;
|
||||||
|
|
||||||
- (void)createContents;
|
- (void)createContents;
|
||||||
|
|
|
@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@property (nonatomic) TSAttachmentStream *attachmentStream;
|
@property (nonatomic) TSAttachmentStream *attachmentStream;
|
||||||
@property (nonatomic) BOOL isIncoming;
|
@property (nonatomic) BOOL isIncoming;
|
||||||
@property (nonatomic, weak) ConversationViewItem *viewItem;
|
@property (nonatomic, weak) id<ConversationViewItem> viewItem;
|
||||||
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
|
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
|
||||||
|
|
||||||
@property (nonatomic, nullable) UIButton *audioPlayPauseButton;
|
@property (nonatomic, nullable) UIButton *audioPlayPauseButton;
|
||||||
|
@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
|
- (instancetype)initWithAttachment:(TSAttachmentStream *)attachmentStream
|
||||||
isIncoming:(BOOL)isIncoming
|
isIncoming:(BOOL)isIncoming
|
||||||
viewItem:(ConversationViewItem *)viewItem
|
viewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle
|
conversationStyle:(ConversationStyle *)conversationStyle
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
|
@ -6,7 +6,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ContactShareViewModel;
|
@class ContactShareViewModel;
|
||||||
@class ConversationStyle;
|
@class ConversationStyle;
|
||||||
@class ConversationViewItem;
|
|
||||||
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@class OWSContact;
|
@class OWSContact;
|
||||||
@class OWSQuotedReplyModel;
|
@class OWSQuotedReplyModel;
|
||||||
@class TSAttachmentPointer;
|
@class TSAttachmentPointer;
|
||||||
|
@ -25,27 +27,27 @@ extern const UIDataDetectorTypes kOWSAllowedDataDetectorTypes;
|
||||||
|
|
||||||
@protocol OWSMessageBubbleViewDelegate
|
@protocol OWSMessageBubbleViewDelegate
|
||||||
|
|
||||||
- (void)didTapImageViewItem:(ConversationViewItem *)viewItem
|
- (void)didTapImageViewItem:(id<ConversationViewItem>)viewItem
|
||||||
attachmentStream:(TSAttachmentStream *)attachmentStream
|
attachmentStream:(TSAttachmentStream *)attachmentStream
|
||||||
imageView:(UIView *)imageView;
|
imageView:(UIView *)imageView;
|
||||||
|
|
||||||
- (void)didTapVideoViewItem:(ConversationViewItem *)viewItem
|
- (void)didTapVideoViewItem:(id<ConversationViewItem>)viewItem
|
||||||
attachmentStream:(TSAttachmentStream *)attachmentStream
|
attachmentStream:(TSAttachmentStream *)attachmentStream
|
||||||
imageView:(UIView *)imageView;
|
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;
|
attachmentPointer:(TSAttachmentPointer *)attachmentPointer;
|
||||||
|
|
||||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply;
|
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem quotedReply:(OWSQuotedReplyModel *)quotedReply;
|
||||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
|
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem
|
||||||
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer;
|
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer;
|
||||||
|
|
||||||
- (void)didTapContactShareViewItem:(ConversationViewItem *)viewItem;
|
- (void)didTapContactShareViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
|
|
||||||
- (void)didTapSendMessageToContactShare:(ContactShareViewModel *)contactShare
|
- (void)didTapSendMessageToContactShare:(ContactShareViewModel *)contactShare
|
||||||
NS_SWIFT_NAME(didTapSendMessage(toContactShare:));
|
NS_SWIFT_NAME(didTapSendMessage(toContactShare:));
|
||||||
|
@ -60,7 +62,7 @@ extern const UIDataDetectorTypes kOWSAllowedDataDetectorTypes;
|
||||||
|
|
||||||
@interface OWSMessageBubbleView : UIView
|
@interface OWSMessageBubbleView : UIView
|
||||||
|
|
||||||
@property (nonatomic, nullable) ConversationViewItem *viewItem;
|
@property (nonatomic, nullable) id<ConversationViewItem> viewItem;
|
||||||
|
|
||||||
@property (nonatomic) ConversationStyle *conversationStyle;
|
@property (nonatomic) ConversationStyle *conversationStyle;
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,20 @@
|
||||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
@class ConversationStyle;
|
|
||||||
@class ConversationViewItem;
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class ConversationStyle;
|
||||||
|
|
||||||
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@interface OWSMessageFooterView : UIStackView
|
@interface OWSMessageFooterView : UIStackView
|
||||||
|
|
||||||
- (void)configureWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (void)configureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
isOverlayingMedia:(BOOL)isOverlayingMedia
|
isOverlayingMedia:(BOOL)isOverlayingMedia
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle
|
conversationStyle:(ConversationStyle *)conversationStyle
|
||||||
isIncoming:(BOOL)isIncoming;
|
isIncoming:(BOOL)isIncoming;
|
||||||
|
|
||||||
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem;
|
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem;
|
||||||
|
|
||||||
- (void)prepareForReuse;
|
- (void)prepareForReuse;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
#pragma mark - Load
|
#pragma mark - Load
|
||||||
|
|
||||||
- (void)configureWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (void)configureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
isOverlayingMedia:(BOOL)isOverlayingMedia
|
isOverlayingMedia:(BOOL)isOverlayingMedia
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle
|
conversationStyle:(ConversationStyle *)conversationStyle
|
||||||
isIncoming:(BOOL)isIncoming
|
isIncoming:(BOOL)isIncoming
|
||||||
|
@ -186,7 +186,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
[self.statusIndicatorImageView.layer addAnimation:animation forKey:@"animation"];
|
[self.statusIndicatorImageView.layer addAnimation:animation forKey:@"animation"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isFailedOutgoingMessage:(ConversationViewItem *)viewItem
|
- (BOOL)isFailedOutgoingMessage:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
return messageStatus == MessageReceiptStatusFailed;
|
return messageStatus == MessageReceiptStatusFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configureLabelsWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (void)configureLabelsWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
self.timestampLabel.text = timestampLabelText.localizedUppercaseString;
|
self.timestampLabel.text = timestampLabelText.localizedUppercaseString;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
return CGSizeCeil(result);
|
return CGSizeCeil(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable NSString *)messageStatusTextForConversationViewItem:(ConversationViewItem *)viewItem
|
- (nullable NSString *)messageStatusTextForConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
if (viewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage) {
|
if (viewItem.interaction.interactionType != OWSInteractionType_OutgoingMessage) {
|
||||||
|
|
|
@ -5,16 +5,17 @@
|
||||||
extern const CGFloat OWSMessageHeaderViewDateHeaderVMargin;
|
extern const CGFloat OWSMessageHeaderViewDateHeaderVMargin;
|
||||||
|
|
||||||
@class ConversationStyle;
|
@class ConversationStyle;
|
||||||
@class ConversationViewItem;
|
|
||||||
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface OWSMessageHeaderView : UIStackView
|
@interface OWSMessageHeaderView : UIStackView
|
||||||
|
|
||||||
- (void)loadForDisplayWithViewItem:(ConversationViewItem *)viewItem
|
- (void)loadForDisplayWithViewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle;
|
conversationStyle:(ConversationStyle *)conversationStyle;
|
||||||
|
|
||||||
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle;
|
conversationStyle:(ConversationStyle *)conversationStyle;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -72,7 +72,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
|
||||||
[self addSubview:self.stackView];
|
[self addSubview:self.stackView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)loadForDisplayWithViewItem:(ConversationViewItem *)viewItem
|
- (void)loadForDisplayWithViewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle
|
conversationStyle:(ConversationStyle *)conversationStyle
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
@ -100,7 +100,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)strokeThicknessWithViewItem:(ConversationViewItem *)viewItem
|
- (CGFloat)strokeThicknessWithViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIColor *)strokeColorWithViewItem:(ConversationViewItem *)viewItem
|
- (UIColor *)strokeColorWithViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configureLabelsWithViewItem:(ConversationViewItem *)viewItem
|
- (void)configureLabelsWithViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ const CGFloat OWSMessageHeaderViewDateHeaderVMargin = 23;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGSize)measureWithConversationViewItem:(ConversationViewItem *)viewItem
|
- (CGSize)measureWithConversationViewItem:(id<ConversationViewItem>)viewItem
|
||||||
conversationStyle:(ConversationStyle *)conversationStyle
|
conversationStyle:(ConversationStyle *)conversationStyle
|
||||||
{
|
{
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
|
|
@ -175,8 +175,8 @@ typedef enum : NSUInteger {
|
||||||
@property (nonatomic, readonly) ConversationViewLayout *layout;
|
@property (nonatomic, readonly) ConversationViewLayout *layout;
|
||||||
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
|
@property (nonatomic, readonly) ConversationStyle *conversationStyle;
|
||||||
|
|
||||||
@property (nonatomic) NSArray<ConversationViewItem *> *viewItems;
|
@property (nonatomic) NSArray<id<ConversationViewItem>> *viewItems;
|
||||||
@property (nonatomic) NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache;
|
@property (nonatomic) NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache;
|
||||||
|
|
||||||
@property (nonatomic, nullable) AVAudioRecorder *audioRecorder;
|
@property (nonatomic, nullable) AVAudioRecorder *audioRecorder;
|
||||||
@property (nonatomic, nullable) OWSAudioPlayer *audioAttachmentPlayer;
|
@property (nonatomic, nullable) OWSAudioPlayer *audioAttachmentPlayer;
|
||||||
|
@ -717,7 +717,7 @@ typedef enum : NSUInteger {
|
||||||
- (NSIndexPath *_Nullable)indexPathOfUnreadMessagesIndicator
|
- (NSIndexPath *_Nullable)indexPathOfUnreadMessagesIndicator
|
||||||
{
|
{
|
||||||
NSInteger row = 0;
|
NSInteger row = 0;
|
||||||
for (ConversationViewItem *viewItem in self.viewItems) {
|
for (id<ConversationViewItem> viewItem in self.viewItems) {
|
||||||
if (viewItem.unreadIndicator) {
|
if (viewItem.unreadIndicator) {
|
||||||
return [NSIndexPath indexPathForRow:row inSection:0];
|
return [NSIndexPath indexPathForRow:row inSection:0];
|
||||||
}
|
}
|
||||||
|
@ -1553,7 +1553,7 @@ typedef enum : NSUInteger {
|
||||||
OWSLogInfo(@"didChangePreferredContentSize");
|
OWSLogInfo(@"didChangePreferredContentSize");
|
||||||
|
|
||||||
// Evacuate cached cell sizes.
|
// Evacuate cached cell sizes.
|
||||||
for (ConversationViewItem *viewItem in self.viewItems) {
|
for (id<ConversationViewItem> viewItem in self.viewItems) {
|
||||||
[viewItem clearCachedLayoutState];
|
[viewItem clearCachedLayoutState];
|
||||||
}
|
}
|
||||||
[self resetContentAndLayout];
|
[self resetContentAndLayout];
|
||||||
|
@ -1933,12 +1933,12 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
#pragma mark - MessageActionsDelegate
|
#pragma mark - MessageActionsDelegate
|
||||||
|
|
||||||
- (void)messageActionsShowDetailsForItem:(ConversationViewItem *)conversationViewItem
|
- (void)messageActionsShowDetailsForItem:(id<ConversationViewItem>)conversationViewItem
|
||||||
{
|
{
|
||||||
[self showDetailViewForViewItem:conversationViewItem];
|
[self showDetailViewForViewItem:conversationViewItem];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)messageActionsReplyToItem:(ConversationViewItem *)conversationViewItem
|
- (void)messageActionsReplyToItem:(id<ConversationViewItem>)conversationViewItem
|
||||||
{
|
{
|
||||||
[self populateReplyForViewItem:conversationViewItem];
|
[self populateReplyForViewItem:conversationViewItem];
|
||||||
}
|
}
|
||||||
|
@ -2006,27 +2006,32 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
#pragma mark - ConversationViewCellDelegate
|
#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];
|
[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];
|
[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];
|
[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];
|
[self presentMessageActions:messageActions withFocusedCell:cell];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2141,7 +2146,7 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
#pragma mark - OWSMessageBubbleViewDelegate
|
#pragma mark - OWSMessageBubbleViewDelegate
|
||||||
|
|
||||||
- (void)didTapImageViewItem:(ConversationViewItem *)viewItem
|
- (void)didTapImageViewItem:(id<ConversationViewItem>)viewItem
|
||||||
attachmentStream:(TSAttachmentStream *)attachmentStream
|
attachmentStream:(TSAttachmentStream *)attachmentStream
|
||||||
imageView:(UIView *)imageView
|
imageView:(UIView *)imageView
|
||||||
{
|
{
|
||||||
|
@ -2172,7 +2177,7 @@ typedef enum : NSUInteger {
|
||||||
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
|
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapVideoViewItem:(ConversationViewItem *)viewItem
|
- (void)didTapVideoViewItem:(id<ConversationViewItem>)viewItem
|
||||||
attachmentStream:(TSAttachmentStream *)attachmentStream
|
attachmentStream:(TSAttachmentStream *)attachmentStream
|
||||||
imageView:(UIImageView *)imageView
|
imageView:(UIImageView *)imageView
|
||||||
{
|
{
|
||||||
|
@ -2201,7 +2206,7 @@ typedef enum : NSUInteger {
|
||||||
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
|
[vc presentDetailViewFromViewController:self mediaMessage:mediaMessage replacingView:imageView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapAudioViewItem:(ConversationViewItem *)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream
|
- (void)didTapAudioViewItem:(id<ConversationViewItem>)viewItem attachmentStream:(TSAttachmentStream *)attachmentStream
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
@ -2231,7 +2236,7 @@ typedef enum : NSUInteger {
|
||||||
[self.audioAttachmentPlayer playWithPlaybackAudioCategory];
|
[self.audioAttachmentPlayer playWithPlaybackAudioCategory];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapTruncatedTextMessage:(ConversationViewItem *)conversationItem
|
- (void)didTapTruncatedTextMessage:(id<ConversationViewItem>)conversationItem
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(conversationItem);
|
OWSAssertDebug(conversationItem);
|
||||||
|
@ -2241,7 +2246,7 @@ typedef enum : NSUInteger {
|
||||||
[self.navigationController pushViewController:view animated:YES];
|
[self.navigationController pushViewController:view animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapContactShareViewItem:(ConversationViewItem *)conversationItem
|
- (void)didTapContactShareViewItem:(id<ConversationViewItem>)conversationItem
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(conversationItem);
|
OWSAssertDebug(conversationItem);
|
||||||
|
@ -2276,7 +2281,7 @@ typedef enum : NSUInteger {
|
||||||
[self.contactShareViewHelper showAddToContactsWithContactShare:contactShare fromViewController:self];
|
[self.contactShareViewHelper showAddToContactsWithContactShare:contactShare fromViewController:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapFailedIncomingAttachment:(ConversationViewItem *)viewItem
|
- (void)didTapFailedIncomingAttachment:(id<ConversationViewItem>)viewItem
|
||||||
attachmentPointer:(TSAttachmentPointer *)attachmentPointer
|
attachmentPointer:(TSAttachmentPointer *)attachmentPointer
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
|
@ -2296,7 +2301,7 @@ typedef enum : NSUInteger {
|
||||||
[self handleUnsentMessageTap:message];
|
[self handleUnsentMessageTap:message];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didTapConversationItem:(ConversationViewItem *)viewItem
|
- (void)didTapConversationItem:(id<ConversationViewItem>)viewItem
|
||||||
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
quotedReply:(OWSQuotedReplyModel *)quotedReply
|
||||||
failedThumbnailDownloadAttachmentPointer:(TSAttachmentPointer *)attachmentPointer
|
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();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(viewItem);
|
OWSAssertDebug(viewItem);
|
||||||
|
@ -2469,7 +2474,7 @@ typedef enum : NSUInteger {
|
||||||
return @(groupIndex);
|
return @(groupIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showDetailViewForViewItem:(ConversationViewItem *)conversationItem
|
- (void)showDetailViewForViewItem:(id<ConversationViewItem>)conversationItem
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(conversationItem);
|
OWSAssertDebug(conversationItem);
|
||||||
|
@ -2484,7 +2489,7 @@ typedef enum : NSUInteger {
|
||||||
[self.navigationController pushViewController:view animated:YES];
|
[self.navigationController pushViewController:view animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)populateReplyForViewItem:(ConversationViewItem *)conversationItem
|
- (void)populateReplyForViewItem:(id<ConversationViewItem>)conversationItem
|
||||||
{
|
{
|
||||||
OWSLogDebug(@"user did tap reply");
|
OWSLogDebug(@"user did tap reply");
|
||||||
|
|
||||||
|
@ -2559,7 +2564,7 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
NSIndexPath *_Nullable indexPathOfUnreadIndicator = [self indexPathOfUnreadMessagesIndicator];
|
NSIndexPath *_Nullable indexPathOfUnreadIndicator = [self indexPathOfUnreadMessagesIndicator];
|
||||||
if (indexPathOfUnreadIndicator) {
|
if (indexPathOfUnreadIndicator) {
|
||||||
ConversationViewItem *oldIndicatorItem = [self viewItemForIndex:indexPathOfUnreadIndicator.row];
|
id<ConversationViewItem> oldIndicatorItem = [self viewItemForIndex:indexPathOfUnreadIndicator.row];
|
||||||
OWSAssertDebug(oldIndicatorItem);
|
OWSAssertDebug(oldIndicatorItem);
|
||||||
|
|
||||||
// TODO ideally this would be happening within the *same* transaction that caused the unreadMessageIndicator
|
// 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;
|
BOOL isScrolledUp = scrollSpaceToBottom > pageHeight * 1.f;
|
||||||
|
|
||||||
if (self.viewItems.count > 0) {
|
if (self.viewItems.count > 0) {
|
||||||
ConversationViewItem *lastViewItem = [self.viewItems lastObject];
|
id<ConversationViewItem> lastViewItem = [self.viewItems lastObject];
|
||||||
OWSAssertDebug(lastViewItem);
|
OWSAssertDebug(lastViewItem);
|
||||||
|
|
||||||
if (lastViewItem.interaction.timestampForSorting > self.lastVisibleTimestamp) {
|
if (lastViewItem.interaction.timestampForSorting > self.lastVisibleTimestamp) {
|
||||||
|
@ -3289,7 +3294,7 @@ typedef enum : NSUInteger {
|
||||||
case YapDatabaseViewChangeUpdate: {
|
case YapDatabaseViewChangeUpdate: {
|
||||||
YapCollectionKey *collectionKey = rowChange.collectionKey;
|
YapCollectionKey *collectionKey = rowChange.collectionKey;
|
||||||
if (collectionKey.key) {
|
if (collectionKey.key) {
|
||||||
ConversationViewItem *_Nullable viewItem = self.viewItemCache[collectionKey.key];
|
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[collectionKey.key];
|
||||||
if (viewItem) {
|
if (viewItem) {
|
||||||
[self reloadInteractionForViewItem:viewItem];
|
[self reloadInteractionForViewItem:viewItem];
|
||||||
} else {
|
} else {
|
||||||
|
@ -3373,7 +3378,8 @@ typedef enum : NSUInteger {
|
||||||
(unsigned long)rowChange.finalIndex);
|
(unsigned long)rowChange.finalIndex);
|
||||||
[self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]];
|
[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]]) {
|
if ([viewItem.interaction isKindOfClass:[TSOutgoingMessage class]]) {
|
||||||
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction;
|
TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)viewItem.interaction;
|
||||||
if (!outgoingMessage.isFromLinkedDevice) {
|
if (!outgoingMessage.isFromLinkedDevice) {
|
||||||
|
@ -3508,7 +3514,7 @@ typedef enum : NSUInteger {
|
||||||
isOnlyModifyingLastMessage = NO;
|
isOnlyModifyingLastMessage = NO;
|
||||||
break;
|
break;
|
||||||
case YapDatabaseViewChangeInsert: {
|
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]] ||
|
if (([viewItem.interaction isKindOfClass:[TSIncomingMessage class]] ||
|
||||||
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
|
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
|
||||||
&& rowChange.finalIndex >= oldViewItemCount) {
|
&& rowChange.finalIndex >= oldViewItemCount) {
|
||||||
|
@ -3524,7 +3530,7 @@ typedef enum : NSUInteger {
|
||||||
if (rowChange.changes == YapDatabaseViewChangedDependency) {
|
if (rowChange.changes == YapDatabaseViewChangedDependency) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ConversationViewItem *_Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
|
id<ConversationViewItem> _Nullable viewItem = [self viewItemForIndex:(NSInteger)rowChange.finalIndex];
|
||||||
if (([viewItem.interaction isKindOfClass:[TSIncomingMessage class]] ||
|
if (([viewItem.interaction isKindOfClass:[TSIncomingMessage class]] ||
|
||||||
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
|
[viewItem.interaction isKindOfClass:[TSOutgoingMessage class]])
|
||||||
&& rowChange.finalIndex >= oldViewItemCount) {
|
&& rowChange.finalIndex >= oldViewItemCount) {
|
||||||
|
@ -3855,7 +3861,7 @@ typedef enum : NSUInteger {
|
||||||
return lastVisibleIndexPath;
|
return lastVisibleIndexPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable ConversationViewItem *)lastVisibleViewItem
|
- (nullable id<ConversationViewItem>)lastVisibleViewItem
|
||||||
{
|
{
|
||||||
NSIndexPath *_Nullable lastVisibleIndexPath = [self lastVisibleIndexPath];
|
NSIndexPath *_Nullable lastVisibleIndexPath = [self lastVisibleIndexPath];
|
||||||
if (!lastVisibleIndexPath) {
|
if (!lastVisibleIndexPath) {
|
||||||
|
@ -3870,7 +3876,7 @@ typedef enum : NSUInteger {
|
||||||
- (void)didScrollToBottom
|
- (void)didScrollToBottom
|
||||||
{
|
{
|
||||||
|
|
||||||
ConversationViewItem *_Nullable lastVisibleViewItem = [self.viewItems lastObject];
|
id<ConversationViewItem> _Nullable lastVisibleViewItem = [self.viewItems lastObject];
|
||||||
if (lastVisibleViewItem) {
|
if (lastVisibleViewItem) {
|
||||||
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
|
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
|
||||||
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
|
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
|
||||||
|
@ -3883,7 +3889,7 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
- (void)updateLastVisibleTimestamp
|
- (void)updateLastVisibleTimestamp
|
||||||
{
|
{
|
||||||
ConversationViewItem *_Nullable lastVisibleViewItem = [self lastVisibleViewItem];
|
id<ConversationViewItem> _Nullable lastVisibleViewItem = [self lastVisibleViewItem];
|
||||||
if (lastVisibleViewItem) {
|
if (lastVisibleViewItem) {
|
||||||
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
|
uint64_t lastVisibleTimestamp = lastVisibleViewItem.interaction.timestampForSorting;
|
||||||
self.lastVisibleTimestamp = MAX(self.lastVisibleTimestamp, lastVisibleTimestamp);
|
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
|
// 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
|
// first item at or after the "view horizon". See the comments below which explain
|
||||||
// the "view horizon".
|
// the "view horizon".
|
||||||
ConversationViewItem *_Nullable lastViewItem = self.viewItems.lastObject;
|
id<ConversationViewItem> _Nullable lastViewItem = self.viewItems.lastObject;
|
||||||
BOOL hasAddedNewItems = (lastViewItem && previousLastTimestamp
|
BOOL hasAddedNewItems = (lastViewItem && previousLastTimestamp
|
||||||
&& lastViewItem.interaction.timestamp > previousLastTimestamp.unsignedLongLongValue);
|
&& 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'll use this later to update the view to reflect any changes made while
|
||||||
// we were not observing the database. See extendRangeToIncludeUnobservedItems
|
// we were not observing the database. See extendRangeToIncludeUnobservedItems
|
||||||
// and the logic above.
|
// and the logic above.
|
||||||
ConversationViewItem *_Nullable lastViewItem = self.viewItems.lastObject;
|
id<ConversationViewItem> _Nullable lastViewItem = self.viewItems.lastObject;
|
||||||
if (lastViewItem) {
|
if (lastViewItem) {
|
||||||
self.previousLastTimestamp = @(lastViewItem.interaction.timestamp);
|
self.previousLastTimestamp = @(lastViewItem.interaction.timestamp);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4717,7 +4723,7 @@ typedef enum : NSUInteger {
|
||||||
NSUInteger mid = (left + right) / 2;
|
NSUInteger mid = (left + right) / 2;
|
||||||
OWSAssertDebug(left <= mid);
|
OWSAssertDebug(left <= mid);
|
||||||
OWSAssertDebug(mid < right);
|
OWSAssertDebug(mid < right);
|
||||||
ConversationViewItem *viewItem = self.viewItems[mid];
|
id<ConversationViewItem> viewItem = self.viewItems[mid];
|
||||||
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
|
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
|
||||||
right = mid;
|
right = mid;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4726,7 +4732,7 @@ typedef enum : NSUInteger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OWSAssertDebug(left == right);
|
OWSAssertDebug(left == right);
|
||||||
ConversationViewItem *viewItem = self.viewItems[left];
|
id<ConversationViewItem> viewItem = self.viewItems[left];
|
||||||
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
|
if (viewItem.interaction.timestamp >= viewHorizonTimestamp) {
|
||||||
OWSLogInfo(@"firstIndexPathAtViewHorizonTimestamp: %zd / %zd", left, self.viewItems.count);
|
OWSLogInfo(@"firstIndexPathAtViewHorizonTimestamp: %zd / %zd", left, self.viewItems.count);
|
||||||
return [NSIndexPath indexPathForRow:(NSInteger) left inSection:0];
|
return [NSIndexPath indexPathForRow:(NSInteger) left inSection:0];
|
||||||
|
@ -4860,8 +4866,8 @@ typedef enum : NSUInteger {
|
||||||
// Returns NO on error.
|
// Returns NO on error.
|
||||||
- (BOOL)reloadViewItems
|
- (BOOL)reloadViewItems
|
||||||
{
|
{
|
||||||
NSMutableArray<ConversationViewItem *> *viewItems = [NSMutableArray new];
|
NSMutableArray<id<ConversationViewItem>> *viewItems = [NSMutableArray new];
|
||||||
NSMutableDictionary<NSString *, ConversationViewItem *> *viewItemCache = [NSMutableDictionary new];
|
NSMutableDictionary<NSString *, id<ConversationViewItem>> *viewItemCache = [NSMutableDictionary new];
|
||||||
|
|
||||||
NSUInteger count = [self.messageMappings numberOfItemsInSection:0];
|
NSUInteger count = [self.messageMappings numberOfItemsInSection:0];
|
||||||
BOOL isGroupThread = self.isGroupConversation;
|
BOOL isGroupThread = self.isGroupConversation;
|
||||||
|
@ -4890,12 +4896,12 @@ typedef enum : NSUInteger {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationViewItem *_Nullable viewItem = self.viewItemCache[interaction.uniqueId];
|
id<ConversationViewItem> _Nullable viewItem = self.viewItemCache[interaction.uniqueId];
|
||||||
if (!viewItem) {
|
if (!viewItem) {
|
||||||
viewItem = [[ConversationViewItem alloc] initWithInteraction:interaction
|
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:interaction
|
||||||
isGroupThread:isGroupThread
|
isGroupThread:isGroupThread
|
||||||
transaction:transaction
|
transaction:transaction
|
||||||
conversationStyle:self.conversationStyle];
|
conversationStyle:self.conversationStyle];
|
||||||
}
|
}
|
||||||
[viewItems addObject:viewItem];
|
[viewItems addObject:viewItem];
|
||||||
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
|
OWSAssertDebug(!viewItemCache[interaction.uniqueId]);
|
||||||
|
@ -4916,7 +4922,7 @@ typedef enum : NSUInteger {
|
||||||
uint64_t collapseCutoffTimestamp = [NSDate ows_millisecondsSince1970ForDate:self.collapseCutoffDate];
|
uint64_t collapseCutoffTimestamp = [NSDate ows_millisecondsSince1970ForDate:self.collapseCutoffDate];
|
||||||
|
|
||||||
BOOL hasPlacedUnreadIndicator = NO;
|
BOOL hasPlacedUnreadIndicator = NO;
|
||||||
for (ConversationViewItem *viewItem in viewItems) {
|
for (id<ConversationViewItem> viewItem in viewItems) {
|
||||||
BOOL canShowDate = NO;
|
BOOL canShowDate = NO;
|
||||||
switch (viewItem.interaction.interactionType) {
|
switch (viewItem.interaction.interactionType) {
|
||||||
case OWSInteractionType_Unknown:
|
case OWSInteractionType_Unknown:
|
||||||
|
@ -4992,9 +4998,9 @@ typedef enum : NSUInteger {
|
||||||
//
|
//
|
||||||
// NOTE: This logic uses the break properties which are set in the previous pass.
|
// NOTE: This logic uses the break properties which are set in the previous pass.
|
||||||
for (NSUInteger i = 0; i < viewItems.count; i++) {
|
for (NSUInteger i = 0; i < viewItems.count; i++) {
|
||||||
ConversationViewItem *viewItem = viewItems[i];
|
id<ConversationViewItem> viewItem = viewItems[i];
|
||||||
ConversationViewItem *_Nullable previousViewItem = (i > 0 ? viewItems[i - 1] : nil);
|
id<ConversationViewItem> _Nullable previousViewItem = (i > 0 ? viewItems[i - 1] : nil);
|
||||||
ConversationViewItem *_Nullable nextViewItem = (i + 1 < viewItems.count ? viewItems[i + 1] : nil);
|
id<ConversationViewItem> _Nullable nextViewItem = (i + 1 < viewItems.count ? viewItems[i + 1] : nil);
|
||||||
BOOL shouldShowSenderAvatar = NO;
|
BOOL shouldShowSenderAvatar = NO;
|
||||||
BOOL shouldHideFooter = NO;
|
BOOL shouldHideFooter = NO;
|
||||||
BOOL isFirstInCluster = YES;
|
BOOL isFirstInCluster = YES;
|
||||||
|
@ -5143,7 +5149,7 @@ typedef enum : NSUInteger {
|
||||||
|
|
||||||
// Whenever an interaction is modified, we need to reload it from the DB
|
// Whenever an interaction is modified, we need to reload it from the DB
|
||||||
// and update the corresponding view item.
|
// and update the corresponding view item.
|
||||||
- (void)reloadInteractionForViewItem:(ConversationViewItem *)viewItem
|
- (void)reloadInteractionForViewItem:(id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
OWSAssertDebug(viewItem);
|
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) {
|
if (index < 0 || index >= (NSInteger)self.viewItems.count) {
|
||||||
OWSFailDebug(@"Invalid view item index: %lu", (unsigned long)index);
|
OWSFailDebug(@"Invalid view item index: %lu", (unsigned long)index);
|
||||||
|
@ -5183,7 +5189,7 @@ typedef enum : NSUInteger {
|
||||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
|
||||||
cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
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];
|
ConversationViewCell *cell = [viewItem dequeueCellForCollectionView:self.collectionView indexPath:indexPath];
|
||||||
if (!cell) {
|
if (!cell) {
|
||||||
OWSFailDebug(@"Could not dequeue cell.");
|
OWSFailDebug(@"Could not dequeue cell.");
|
||||||
|
|
|
@ -43,7 +43,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
||||||
//
|
//
|
||||||
// Critically, this class implements ConversationViewLayoutItem
|
// Critically, this class implements ConversationViewLayoutItem
|
||||||
// and does caching of the cell's size.
|
// and does caching of the cell's size.
|
||||||
@interface ConversationViewItem : NSObject <ConversationViewLayoutItem, OWSAudioPlayerDelegate>
|
@protocol ConversationViewItem <NSObject, ConversationViewLayoutItem, OWSAudioPlayerDelegate>
|
||||||
|
|
||||||
@property (nonatomic, readonly) TSInteraction *interaction;
|
@property (nonatomic, readonly) TSInteraction *interaction;
|
||||||
|
|
||||||
|
@ -69,14 +69,6 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
||||||
|
|
||||||
@property (nonatomic, nullable) OWSUnreadIndicator *unreadIndicator;
|
@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
|
- (ConversationViewCell *)dequeueCellForCollectionView:(UICollectionView *)collectionView
|
||||||
indexPath:(NSIndexPath *)indexPath;
|
indexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
@ -89,21 +81,20 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
||||||
@property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView;
|
@property (nonatomic, weak) OWSAudioMessageView *lastAudioMessageView;
|
||||||
|
|
||||||
@property (nonatomic, readonly) CGFloat audioDurationSeconds;
|
@property (nonatomic, readonly) CGFloat audioDurationSeconds;
|
||||||
|
@property (nonatomic, readonly) CGFloat audioProgressSeconds;
|
||||||
- (CGFloat)audioProgressSeconds;
|
|
||||||
|
|
||||||
#pragma mark - View State Caching
|
#pragma mark - View State Caching
|
||||||
|
|
||||||
// These methods only apply to text & attachment messages.
|
// These methods only apply to text & attachment messages.
|
||||||
- (OWSMessageCellType)messageCellType;
|
@property (nonatomic, readonly) OWSMessageCellType messageCellType;
|
||||||
- (nullable DisplayableText *)displayableBodyText;
|
@property (nonatomic, readonly, nullable) DisplayableText *displayableBodyText;
|
||||||
- (nullable TSAttachmentStream *)attachmentStream;
|
@property (nonatomic, readonly, nullable) TSAttachmentStream *attachmentStream;
|
||||||
- (nullable TSAttachmentPointer *)attachmentPointer;
|
@property (nonatomic, readonly, nullable) TSAttachmentPointer *attachmentPointer;
|
||||||
- (CGSize)mediaSize;
|
@property (nonatomic, readonly) CGSize mediaSize;
|
||||||
|
|
||||||
- (nullable DisplayableText *)displayableQuotedText;
|
@property (nonatomic, readonly, nullable) DisplayableText *displayableQuotedText;
|
||||||
- (nullable NSString *)quotedAttachmentMimetype;
|
@property (nonatomic, readonly, nullable) NSString *quotedAttachmentMimetype;
|
||||||
- (nullable NSString *)quotedRecipientId;
|
@property (nonatomic, readonly, nullable) NSString *quotedRecipientId;
|
||||||
|
|
||||||
// We don't want to try to load the media for this item (if any)
|
// We don't want to try to load the media for this item (if any)
|
||||||
// if a load has previously failed.
|
// if a load has previously failed.
|
||||||
|
@ -132,4 +123,15 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType);
|
||||||
|
|
||||||
@end
|
@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
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
|
@ -46,7 +46,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
@interface ConversationViewItem ()
|
@interface ConversationInteractionViewItem ()
|
||||||
|
|
||||||
@property (nonatomic, nullable) NSValue *cachedCellSize;
|
@property (nonatomic, nullable) NSValue *cachedCellSize;
|
||||||
|
|
||||||
|
@ -70,12 +70,25 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||||
@property (nonatomic, nullable) NSString *systemMessageText;
|
@property (nonatomic, nullable) NSString *systemMessageText;
|
||||||
@property (nonatomic, nullable) TSThread *incomingMessageAuthorThread;
|
@property (nonatomic, nullable) TSThread *incomingMessageAuthorThread;
|
||||||
@property (nonatomic, nullable) NSString *authorConversationColorName;
|
@property (nonatomic, nullable) NSString *authorConversationColorName;
|
||||||
|
@property (nonatomic, nullable) ConversationStyle *conversationStyle;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark -
|
#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
|
- (instancetype)initWithInteraction:(TSInteraction *)interaction
|
||||||
isGroupThread:(BOOL)isGroupThread
|
isGroupThread:(BOOL)isGroupThread
|
||||||
|
@ -293,7 +306,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
|
||||||
return measurementCell;
|
return measurementCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)vSpacingWithPreviousLayoutItem:(ConversationViewItem *)previousLayoutItem
|
- (CGFloat)vSpacingWithPreviousLayoutItem:(id<ConversationViewItem>)previousLayoutItem
|
||||||
{
|
{
|
||||||
OWSAssertDebug(previousLayoutItem);
|
OWSAssertDebug(previousLayoutItem);
|
||||||
|
|
||||||
|
|
|
@ -1967,10 +1967,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
OWSAssertDebug(messageToQuote);
|
OWSAssertDebug(messageToQuote);
|
||||||
OWSLogVerbose(@"%@", label);
|
OWSLogVerbose(@"%@", label);
|
||||||
[DDLog flushLog];
|
[DDLog flushLog];
|
||||||
ConversationViewItem *viewItem = [[ConversationViewItem alloc] initWithInteraction:messageToQuote
|
id<ConversationViewItem> viewItem =
|
||||||
isGroupThread:thread.isGroupThread
|
[[ConversationInteractionViewItem alloc] initWithInteraction:messageToQuote
|
||||||
transaction:transaction
|
isGroupThread:thread.isGroupThread
|
||||||
conversationStyle:conversationStyle];
|
transaction:transaction
|
||||||
|
conversationStyle:conversationStyle];
|
||||||
quotedMessage = [
|
quotedMessage = [
|
||||||
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
|
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
|
||||||
buildQuotedMessageForSending];
|
buildQuotedMessageForSending];
|
||||||
|
@ -1986,10 +1987,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
transaction:transaction];
|
transaction:transaction];
|
||||||
OWSAssertDebug(messageToQuote);
|
OWSAssertDebug(messageToQuote);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = [[ConversationViewItem alloc] initWithInteraction:messageToQuote
|
id<ConversationViewItem> viewItem =
|
||||||
isGroupThread:thread.isGroupThread
|
[[ConversationInteractionViewItem alloc] initWithInteraction:messageToQuote
|
||||||
transaction:transaction
|
isGroupThread:thread.isGroupThread
|
||||||
conversationStyle:conversationStyle];
|
transaction:transaction
|
||||||
|
conversationStyle:conversationStyle];
|
||||||
quotedMessage = [
|
quotedMessage = [
|
||||||
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
|
[OWSQuotedReplyModel quotedReplyForSendingWithConversationViewItem:viewItem transaction:transaction]
|
||||||
buildQuotedMessageForSending];
|
buildQuotedMessageForSending];
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class LongTextViewController: OWSViewController {
|
||||||
guard viewItem.hasBodyText else {
|
guard viewItem.hasBodyText else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
guard let displayableText = viewItem.displayableBodyText() else {
|
guard let displayableText = viewItem.displayableBodyText else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
let messageBody = displayableText.fullText
|
let messageBody = displayableText.fullText
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ConversationViewItem;
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@class GalleryItemBox;
|
@class GalleryItemBox;
|
||||||
@class MediaDetailViewController;
|
@class MediaDetailViewController;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
|
||||||
@protocol MediaDetailViewControllerDelegate <NSObject>
|
@protocol MediaDetailViewControllerDelegate <NSObject>
|
||||||
|
|
||||||
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
||||||
requestDeleteConversationViewItem:(ConversationViewItem *)conversationViewItem;
|
requestDeleteConversationViewItem:(id<ConversationViewItem>)conversationViewItem;
|
||||||
|
|
||||||
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
- (void)mediaDetailViewController:(MediaDetailViewController *)mediaDetailViewController
|
||||||
isPlayingVideo:(BOOL)isPlayingVideo;
|
isPlayingVideo:(BOOL)isPlayingVideo;
|
||||||
|
@ -34,7 +35,7 @@ typedef NS_OPTIONS(NSInteger, MediaGalleryOption) {
|
||||||
|
|
||||||
// If viewItem is non-null, long press will show a menu controller.
|
// If viewItem is non-null, long press will show a menu controller.
|
||||||
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
|
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
|
||||||
viewItem:(ConversationViewItem *_Nullable)viewItem;
|
viewItem:(nullable id<ConversationViewItem>)viewItem;
|
||||||
#pragma mark - Actions
|
#pragma mark - Actions
|
||||||
|
|
||||||
- (void)didPressShare:(id)sender;
|
- (void)didPressShare:(id)sender;
|
||||||
|
|
|
@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
@property (nonatomic) UIButton *shareButton;
|
@property (nonatomic) UIButton *shareButton;
|
||||||
|
|
||||||
@property (nonatomic) TSAttachmentStream *attachmentStream;
|
@property (nonatomic) TSAttachmentStream *attachmentStream;
|
||||||
@property (nonatomic, nullable) ConversationViewItem *viewItem;
|
@property (nonatomic, nullable) id<ConversationViewItem> viewItem;
|
||||||
@property (nonatomic, nullable) UIImage *image;
|
@property (nonatomic, nullable) UIImage *image;
|
||||||
|
|
||||||
@property (nonatomic, nullable) OWSVideoPlayer *videoPlayer;
|
@property (nonatomic, nullable) OWSVideoPlayer *videoPlayer;
|
||||||
|
@ -63,7 +63,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
|
- (instancetype)initWithGalleryItemBox:(GalleryItemBox *)galleryItemBox
|
||||||
viewItem:(ConversationViewItem *_Nullable)viewItem
|
viewItem:(nullable id<ConversationViewItem>)viewItem
|
||||||
{
|
{
|
||||||
self = [super initWithNibName:nil bundle:nil];
|
self = [super initWithNibName:nil bundle:nil];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
|
|
|
@ -479,10 +479,10 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
|
||||||
let message = galleryItem.message
|
let message = galleryItem.message
|
||||||
let thread = message.thread(with: transaction)
|
let thread = message.thread(with: transaction)
|
||||||
let conversationStyle = ConversationStyle(thread: thread)
|
let conversationStyle = ConversationStyle(thread: thread)
|
||||||
fetchedItem = ConversationViewItem(interaction: message,
|
fetchedItem = ConversationInteractionViewItem(interaction: message,
|
||||||
isGroupThread: thread.isGroupThread(),
|
isGroupThread: thread.isGroupThread(),
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
conversationStyle: conversationStyle)
|
conversationStyle: conversationStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let viewItem = fetchedItem else {
|
guard let viewItem = fetchedItem else {
|
||||||
|
|
|
@ -326,7 +326,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
|
||||||
guard viewItem.hasBodyText else {
|
guard viewItem.hasBodyText else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
guard let displayableText = viewItem.displayableBodyText() else {
|
guard let displayableText = viewItem.displayableBodyText else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let messageBody = displayableText.fullText
|
let messageBody = displayableText.fullText
|
||||||
|
@ -663,7 +663,7 @@ class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDele
|
||||||
|
|
||||||
if let audioAttachmentPlayer = self.audioAttachmentPlayer {
|
if let audioAttachmentPlayer = self.audioAttachmentPlayer {
|
||||||
// Is this player associated with this media adapter?
|
// Is this player associated with this media adapter?
|
||||||
if audioAttachmentPlayer.owner as? ConversationViewItem == viewItem {
|
if audioAttachmentPlayer.owner === viewItem {
|
||||||
// Tap to pause & unpause.
|
// Tap to pause & unpause.
|
||||||
audioAttachmentPlayer.togglePlayState()
|
audioAttachmentPlayer.togglePlayState()
|
||||||
return
|
return
|
||||||
|
|
|
@ -39,22 +39,22 @@
|
||||||
return @"abc";
|
return @"abc";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)textViewItem
|
- (ConversationInteractionViewItem *)textViewItem
|
||||||
{
|
{
|
||||||
TSOutgoingMessage *message =
|
TSOutgoingMessage *message =
|
||||||
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:self.fakeTextMessageText attachmentId:nil];
|
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:self.fakeTextMessageText attachmentId:nil];
|
||||||
[message save];
|
[message save];
|
||||||
__block ConversationViewItem *viewItem = nil;
|
__block ConversationInteractionViewItem *viewItem = nil;
|
||||||
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
viewItem = [[ConversationViewItem alloc] initWithInteraction:message
|
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:message
|
||||||
isGroupThread:NO
|
isGroupThread:NO
|
||||||
transaction:transaction
|
transaction:transaction
|
||||||
conversationStyle:self.conversationStyle];
|
conversationStyle:self.conversationStyle];
|
||||||
}];
|
}];
|
||||||
return viewItem;
|
return viewItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)viewItemWithAttachmentMimetype:(NSString *)mimeType filename:(NSString *)filename
|
- (ConversationInteractionViewItem *)viewItemWithAttachmentMimetype:(NSString *)mimeType filename:(NSString *)filename
|
||||||
{
|
{
|
||||||
OWSAssertDebug(filename.length > 0);
|
OWSAssertDebug(filename.length > 0);
|
||||||
|
|
||||||
|
@ -74,33 +74,33 @@
|
||||||
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:nil attachmentId:attachment.uniqueId];
|
[TSOutgoingMessage outgoingMessageInThread:self.thread messageBody:nil attachmentId:attachment.uniqueId];
|
||||||
[message save];
|
[message save];
|
||||||
|
|
||||||
__block ConversationViewItem *viewItem = nil;
|
__block ConversationInteractionViewItem *viewItem = nil;
|
||||||
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
[self readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
viewItem = [[ConversationViewItem alloc] initWithInteraction:message
|
viewItem = [[ConversationInteractionViewItem alloc] initWithInteraction:message
|
||||||
isGroupThread:NO
|
isGroupThread:NO
|
||||||
transaction:transaction
|
transaction:transaction
|
||||||
conversationStyle:self.conversationStyle];
|
conversationStyle:self.conversationStyle];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return viewItem;
|
return viewItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)stillImageViewItem
|
- (ConversationInteractionViewItem *)stillImageViewItem
|
||||||
{
|
{
|
||||||
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageJpeg filename:@"test-jpg.jpg"];
|
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageJpeg filename:@"test-jpg.jpg"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)animatedImageViewItem
|
- (ConversationInteractionViewItem *)animatedImageViewItem
|
||||||
{
|
{
|
||||||
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageGif filename:@"test-gif.gif"];
|
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageGif filename:@"test-gif.gif"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)videoViewItem
|
- (ConversationInteractionViewItem *)videoViewItem
|
||||||
{
|
{
|
||||||
return [self viewItemWithAttachmentMimetype:@"video/mp4" filename:@"test-mp4.mp4"];
|
return [self viewItemWithAttachmentMimetype:@"video/mp4" filename:@"test-mp4.mp4"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ConversationViewItem *)audioViewItem
|
- (ConversationInteractionViewItem *)audioViewItem
|
||||||
{
|
{
|
||||||
return [self viewItemWithAttachmentMimetype:@"audio/mp3" filename:@"test-mp3.mp3"];
|
return [self viewItemWithAttachmentMimetype:@"audio/mp3" filename:@"test-mp3.mp3"];
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
|
|
||||||
- (void)testPerformDeleteEditingActionWithNonMediaMessage
|
- (void)testPerformDeleteEditingActionWithNonMediaMessage
|
||||||
{
|
{
|
||||||
ConversationViewItem *viewItem = self.textViewItem;
|
ConversationInteractionViewItem *viewItem = self.textViewItem;
|
||||||
|
|
||||||
XCTAssertNotNil([TSMessage fetchObjectWithUniqueID:viewItem.interaction.uniqueId]);
|
XCTAssertNotNil([TSMessage fetchObjectWithUniqueID:viewItem.interaction.uniqueId]);
|
||||||
[viewItem deleteAction];
|
[viewItem deleteAction];
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
|
|
||||||
- (void)testPerformDeleteActionWithPhotoMessage
|
- (void)testPerformDeleteActionWithPhotoMessage
|
||||||
{
|
{
|
||||||
ConversationViewItem *viewItem = self.stillImageViewItem;
|
ConversationInteractionViewItem *viewItem = self.stillImageViewItem;
|
||||||
|
|
||||||
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
||||||
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
|
|
||||||
- (void)testPerformDeleteEditingActionWithAnimatedMessage
|
- (void)testPerformDeleteEditingActionWithAnimatedMessage
|
||||||
{
|
{
|
||||||
ConversationViewItem *viewItem = self.animatedImageViewItem;
|
ConversationInteractionViewItem *viewItem = self.animatedImageViewItem;
|
||||||
|
|
||||||
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
||||||
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
||||||
|
@ -162,7 +162,7 @@
|
||||||
|
|
||||||
- (void)testPerformDeleteEditingActionWithVideoMessage
|
- (void)testPerformDeleteEditingActionWithVideoMessage
|
||||||
{
|
{
|
||||||
ConversationViewItem *viewItem = self.videoViewItem;
|
ConversationInteractionViewItem *viewItem = self.videoViewItem;
|
||||||
|
|
||||||
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
||||||
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
||||||
|
@ -184,7 +184,7 @@
|
||||||
|
|
||||||
- (void)testPerformDeleteEditingActionWithAudioMessage
|
- (void)testPerformDeleteEditingActionWithAudioMessage
|
||||||
{
|
{
|
||||||
ConversationViewItem *viewItem = self.audioViewItem;
|
ConversationInteractionViewItem *viewItem = self.audioViewItem;
|
||||||
|
|
||||||
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
XCTAssertEqual((NSUInteger)1, ((TSMessage *)viewItem.interaction).attachmentIds.count);
|
||||||
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
NSString *_Nullable attachmentId = ((TSMessage *)viewItem.interaction).attachmentIds.firstObject;
|
||||||
|
@ -212,7 +212,7 @@
|
||||||
UIPasteboard.generalPasteboard.items = @[];
|
UIPasteboard.generalPasteboard.items = @[];
|
||||||
XCTAssertNil(UIPasteboard.generalPasteboard.string);
|
XCTAssertNil(UIPasteboard.generalPasteboard.string);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = self.textViewItem;
|
ConversationInteractionViewItem *viewItem = self.textViewItem;
|
||||||
[viewItem copyTextAction];
|
[viewItem copyTextAction];
|
||||||
XCTAssertEqualObjects(self.fakeTextMessageText, UIPasteboard.generalPasteboard.string);
|
XCTAssertEqualObjects(self.fakeTextMessageText, UIPasteboard.generalPasteboard.string);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@
|
||||||
XCTAssertNil(UIPasteboard.generalPasteboard.image);
|
XCTAssertNil(UIPasteboard.generalPasteboard.image);
|
||||||
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG]);
|
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG]);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = self.stillImageViewItem;
|
ConversationInteractionViewItem *viewItem = self.stillImageViewItem;
|
||||||
[viewItem copyMediaAction];
|
[viewItem copyMediaAction];
|
||||||
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG];
|
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeJPEG];
|
||||||
XCTAssertTrue(copiedData.length > 0);
|
XCTAssertTrue(copiedData.length > 0);
|
||||||
|
@ -237,7 +237,7 @@
|
||||||
XCTAssertNil(UIPasteboard.generalPasteboard.image);
|
XCTAssertNil(UIPasteboard.generalPasteboard.image);
|
||||||
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF]);
|
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF]);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = self.animatedImageViewItem;
|
ConversationInteractionViewItem *viewItem = self.animatedImageViewItem;
|
||||||
[viewItem copyMediaAction];
|
[viewItem copyMediaAction];
|
||||||
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF];
|
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeGIF];
|
||||||
XCTAssertTrue(copiedData.length > 0);
|
XCTAssertTrue(copiedData.length > 0);
|
||||||
|
@ -249,7 +249,7 @@
|
||||||
UIPasteboard.generalPasteboard.items = @[];
|
UIPasteboard.generalPasteboard.items = @[];
|
||||||
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4]);
|
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4]);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = self.videoViewItem;
|
ConversationInteractionViewItem *viewItem = self.videoViewItem;
|
||||||
[viewItem copyMediaAction];
|
[viewItem copyMediaAction];
|
||||||
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4];
|
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4];
|
||||||
XCTAssertTrue(copiedData.length > 0);
|
XCTAssertTrue(copiedData.length > 0);
|
||||||
|
@ -261,7 +261,7 @@
|
||||||
UIPasteboard.generalPasteboard.items = @[];
|
UIPasteboard.generalPasteboard.items = @[];
|
||||||
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3]);
|
XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3]);
|
||||||
|
|
||||||
ConversationViewItem *viewItem = self.audioViewItem;
|
ConversationInteractionViewItem *viewItem = self.audioViewItem;
|
||||||
[viewItem copyMediaAction];
|
[viewItem copyMediaAction];
|
||||||
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3];
|
NSData *_Nullable copiedData = [UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3];
|
||||||
XCTAssertTrue(copiedData.length > 0);
|
XCTAssertTrue(copiedData.length > 0);
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ConversationViewItem;
|
@protocol ConversationViewItem;
|
||||||
|
|
||||||
@class TSAttachmentPointer;
|
@class TSAttachmentPointer;
|
||||||
@class TSAttachmentStream;
|
@class TSAttachmentStream;
|
||||||
@class TSMessage;
|
@class TSMessage;
|
||||||
|
@ -42,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
||||||
// Builds a not-yet-sent QuotedReplyModel
|
// Builds a not-yet-sent QuotedReplyModel
|
||||||
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(ConversationViewItem *)conversationItem
|
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(id<ConversationViewItem>)conversationItem
|
||||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
||||||
- (TSQuotedMessage *)buildQuotedMessageForSending;
|
- (TSQuotedMessage *)buildQuotedMessageForSending;
|
||||||
|
|
|
@ -115,7 +115,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
thumbnailDownloadFailed:thumbnailDownloadFailed];
|
thumbnailDownloadFailed:thumbnailDownloadFailed];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(ConversationViewItem *)conversationItem
|
+ (nullable instancetype)quotedReplyForSendingWithConversationViewItem:(id<ConversationViewItem>)conversationItem
|
||||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
{
|
{
|
||||||
OWSAssertDebug(conversationItem);
|
OWSAssertDebug(conversationItem);
|
||||||
|
|
Loading…
Reference in New Issue