extract QuotedReplyDraft model

This commit is contained in:
Michael Kirk 2018-04-06 10:59:23 -04:00
parent 0b8b3b4f16
commit 253435b27f
15 changed files with 187 additions and 98 deletions

View file

@ -209,11 +209,15 @@ NS_ASSUME_NONNULL_BEGIN
if (!self.hasQuotedAttachmentThumbnailImage) {
return nil;
}
// TODO: Possibly ignore data that is too large.
UIImage *_Nullable image = self.quotedMessage.thumbnailImage;
// TODO: Possibly ignore images that are too large.
return image;
// FIXME
return nil;
//
// // TODO: Possibly ignore data that is too large.
// UIImage *_Nullable image = self.quotedMessage.thumbnailImage;
// // TODO: Possibly ignore images that are too large.
// return image;
}
- (UIImageView *)imageViewForImage:(UIImage *)image
@ -239,7 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
NSString *text = @"";
NSString *_Nullable fileTypeForSnippet = [self fileTypeForSnippet];
NSString *_Nullable sourceFilename = [self.quotedMessage.firstThumbnailAttachment.sourceFilename filterStringForDisplay];
NSString *_Nullable sourceFilename = [self.quotedMessage.sourceFilename filterStringForDisplay];
if (self.displayableQuotedText.displayText.length > 0) {
text = self.displayableQuotedText.displayText;

View file

@ -4,8 +4,8 @@
NS_ASSUME_NONNULL_BEGIN
@class OWSQuotedReplyDraft;
@class SignalAttachment;
@class TSQuotedMessage;
@protocol ConversationInputToolbarDelegate <NSObject>
@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)cancelVoiceMemoIfNecessary;
@property (nonatomic, nullable) TSQuotedMessage *quotedMessage;
@property (nonatomic, nullable) OWSQuotedReplyDraft *quotedReplyDraft;
@end

View file

@ -250,9 +250,9 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
[self ensureContentConstraints];
}
- (void)setQuotedMessage:(nullable TSQuotedMessage *)quotedMessage
- (void)setQuotedMessage:(nullable OWSQuotedReplyDraft *)quotedReplyDraft
{
if (quotedMessage == _quotedMessage) {
if (quotedReplyDraft == _quotedReplyDraft) {
return;
}
@ -261,14 +261,14 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
}
OWSAssert(self.quotedMessagePreview == nil);
_quotedMessage = quotedMessage;
_quotedReplyDraft = quotedReplyDraft;
if (!quotedMessage) {
if (!quotedReplyDraft) {
[self clearQuotedMessagePreview];
return;
}
self.quotedMessagePreview = [[QuotedReplyPreview alloc] initWithQuotedMessage:quotedMessage];
self.quotedMessagePreview = [[QuotedReplyPreview alloc] initWithQuotedReplyDraft:quotedReplyDraft];
self.quotedMessagePreview.delegate = self;
// TODO animate
@ -759,7 +759,7 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
- (void)quotedReplyPreviewDidPressCancel:(QuotedReplyPreview *)preview
{
self.quotedMessage = nil;
self.quotedReplyDraft = nil;
}
@end

View file

@ -2149,17 +2149,17 @@ typedef enum : NSUInteger {
return;
}
__block TSQuotedMessage *quotedMessage;
__block OWSQuotedReplyDraft *quotedReplyDraft;
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
quotedMessage = [OWSMessageUtils quotedMessageForMessage:message transaction:transaction];
quotedReplyDraft = [OWSMessageUtils quotedReplyDraftForMessage:message transaction:transaction];
}];
if (![quotedMessage isKindOfClass:[TSQuotedMessage class]]) {
OWSFail(@"%@ unexpected quotedMessage: %@", self.logTag, quotedMessage);
if (![quotedReplyDraft isKindOfClass:[OWSQuotedReplyDraft class]]) {
OWSFail(@"%@ unexpected quotedMessage: %@", self.logTag, quotedReplyDraft.class);
return;
}
[self.inputToolbar setQuotedMessage:quotedMessage];
self.inputToolbar.quotedReplyDraft = quotedReplyDraft;
[self.inputToolbar beginEditingTextMessage];
}
@ -2430,7 +2430,7 @@ typedef enum : NSUInteger {
[self updateLastVisibleTimestamp:message.timestampForSorting];
self.lastMessageSentDate = [NSDate new];
[self clearUnreadMessagesIndicator];
self.inputToolbar.quotedMessage = nil;
self.inputToolbar.quotedReplyDraft = nil;
if ([Environment.preferences soundInForeground]) {
[JSQSystemSoundPlayer jsq_playMessageSentSound];
@ -2764,10 +2764,12 @@ typedef enum : NSUInteger {
DDLogVerbose(@"Sending attachment. Size in bytes: %lu, contentType: %@",
(unsigned long)[attachment dataLength],
[attachment mimeType]);
TSQuotedMessage *_Nullable quotedMessage = [self.inputToolbar.quotedReplyDraft buildQuotedMessage];
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
TSOutgoingMessage *message = [ThreadUtil sendMessageWithAttachment:attachment
inThread:self.thread
quotedMessage:self.inputToolbar.quotedMessage
quotedMessage:quotedMessage
messageSender:self.messageSender
completion:nil];
@ -4024,19 +4026,21 @@ typedef enum : NSUInteger {
// which are presented as normal text messages.
BOOL didAddToProfileWhitelist = [ThreadUtil addThreadToProfileWhitelistIfEmptyContactThread:self.thread];
TSOutgoingMessage *message;
TSQuotedMessage *_Nullable quotedMessage = [self.inputToolbar.quotedReplyDraft buildQuotedMessage];
if ([text lengthOfBytesUsingEncoding:NSUTF8StringEncoding] >= kOversizeTextMessageSizeThreshold) {
DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithOversizeText:text];
SignalAttachment *attachment =
[SignalAttachment attachmentWithDataSource:dataSource dataUTI:kOversizeTextAttachmentUTI];
message = [ThreadUtil sendMessageWithAttachment:attachment
inThread:self.thread
quotedMessage:self.inputToolbar.quotedMessage
quotedMessage:quotedMessage
messageSender:self.messageSender
completion:nil];
} else {
message = [ThreadUtil sendMessageWithText:text
inThread:self.thread
quotedMessage:self.inputToolbar.quotedMessage
quotedMessage:quotedMessage
messageSender:self.messageSender];
}

View file

@ -1969,7 +1969,8 @@ isQuotedMessageAttachmentDownloaded:(BOOL)isQuotedMessageAttachmentDownloaded
quotedMessage:nil
transaction:transaction];
OWSAssert(messageToQuote);
quotedMessage = [OWSMessageUtils quotedMessageForMessage:messageToQuote transaction:transaction];
quotedMessage = [[OWSMessageUtils quotedReplyDraftForMessage:messageToQuote transaction:transaction]
buildQuotedMessage];
} else {
TSOutgoingMessage *_Nullable messageToQuote = [self createFakeOutgoingMessage:thread
messageBody:quotedMessageBodyWIndex
@ -1980,7 +1981,8 @@ isQuotedMessageAttachmentDownloaded:(BOOL)isQuotedMessageAttachmentDownloaded
quotedMessage:nil
transaction:transaction];
OWSAssert(messageToQuote);
quotedMessage = [OWSMessageUtils quotedMessageForMessage:messageToQuote transaction:transaction];
quotedMessage = [[OWSMessageUtils quotedReplyDraftForMessage:messageToQuote transaction:transaction]
buildQuotedMessage];
}
OWSAssert(quotedMessage);

View file

@ -17,10 +17,10 @@ class QuotedReplyPreview: UIView {
fatalError("init(coder:) has not been implemented")
}
init(quotedMessage: TSQuotedMessage) {
init(quotedReplyDraft: OWSQuotedReplyDraft) {
super.init(frame: .zero)
let isQuotingSelf = quotedMessage.authorId == TSAccountManager.localNumber()
let isQuotingSelf = quotedReplyDraft.authorId == TSAccountManager.localNumber()
// used for stripe and author
// FIXME actual colors TBD
@ -34,7 +34,7 @@ class QuotedReplyPreview: UIView {
if isQuotingSelf {
authorLabel.text = NSLocalizedString("MEDIA_GALLERY_SENDER_NAME_YOU", comment: "")
} else {
authorLabel.text = Environment.current().contactsManager.displayName(forPhoneIdentifier: quotedMessage.authorId)
authorLabel.text = Environment.current().contactsManager.displayName(forPhoneIdentifier: quotedReplyDraft.authorId)
}
authorLabel.font = .ows_dynamicTypeHeadline
@ -43,16 +43,16 @@ class QuotedReplyPreview: UIView {
bodyLabel.font = .ows_footnote
bodyLabel.text = {
if let contentType = quotedMessage.contentType() {
if let contentType = quotedReplyDraft.contentType() {
let emoji = TSAttachmentStream.emoji(forMimeType: contentType)
return "\(emoji) \(quotedMessage.body ?? "")"
return "\(emoji) \(quotedReplyDraft.body ?? "")"
} else {
return quotedMessage.body
return quotedReplyDraft.body
}
}()
let thumbnailView: UIView? = {
if let image = quotedMessage.thumbnailImage() {
if let image = quotedReplyDraft.thumbnailImage() {
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.autoPinToSquareAspectRatio()

View file

@ -86,11 +86,11 @@ NS_ASSUME_NONNULL_BEGIN
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
uint32_t expiresInSeconds = (configuration.isEnabled ? configuration.durationSeconds : 0);
TSOutgoingMessage *message =
[TSOutgoingMessage outgoingMessageInThread:thread
messageBody:text
attachmentId:nil
expiresInSeconds:expiresInSeconds];
TSOutgoingMessage *message = [TSOutgoingMessage outgoingMessageInThread:thread
messageBody:text
attachmentId:nil
expiresInSeconds:expiresInSeconds
quotedMessage:quotedMessage];
[messageSender enqueueMessage:message success:successHandler failure:failureHandler];
@ -132,11 +132,10 @@ NS_ASSUME_NONNULL_BEGIN
inThread:thread
messageBody:attachment.captionText
attachmentIds:[NSMutableArray new]
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)
expireStartedAt:0
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)expireStartedAt:0
isVoiceMessage:[attachment isVoiceMessage]
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
quotedMessage:quotedMessage];
[messageSender enqueueAttachment:attachment.dataSource
contentType:attachment.mimeType

View file

@ -66,6 +66,12 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
attachmentId:(nullable NSString *)attachmentId
expiresInSeconds:(uint32_t)expiresInSeconds;
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentId:(nullable NSString *)attachmentId
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage;
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage;

View file

@ -79,13 +79,30 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
messageBody:(nullable NSString *)body
attachmentId:(nullable NSString *)attachmentId
{
return [self outgoingMessageInThread:thread messageBody:body attachmentId:attachmentId expiresInSeconds:0];
return [self outgoingMessageInThread:thread
messageBody:body
attachmentId:attachmentId
expiresInSeconds:0
quotedMessage:nil];
}
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentId:(nullable NSString *)attachmentId
expiresInSeconds:(uint32_t)expiresInSeconds
{
return [self outgoingMessageInThread:thread
messageBody:body
attachmentId:attachmentId
expiresInSeconds:expiresInSeconds
quotedMessage:nil];
}
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentId:(nullable NSString *)attachmentId
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
{
NSMutableArray<NSString *> *attachmentIds = [NSMutableArray new];
if (attachmentId) {
@ -99,7 +116,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
quotedMessage:quotedMessage];
}
+ (instancetype)outgoingMessageInThread:(nullable TSThread *)thread

View file

@ -2,13 +2,42 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalServiceKit/TSYapDatabaseObject.h>
#import <Mantle/MTLModel.h>
#import <SignalServiceKit/TSYapDatabaseObject.h>
NS_ASSUME_NONNULL_BEGIN
@class TSAttachment;
@class TSAttachmentStream;
@class TSQuotedMessage;
@interface OWSQuotedReplyDraft : NSObject
@property (nonatomic, readonly) uint64_t timestamp;
@property (nonatomic, readonly) NSString *authorId;
@property (nonatomic, readonly, nullable) TSAttachmentStream *attachmentStream;
// This property should be set IFF we are quoting a text message
// or attachment with caption.
@property (nullable, nonatomic, readonly) NSString *body;
#pragma mark - Attachments
// This is a MIME type.
//
// This property should be set IFF we are quoting an attachment message.
- (nullable NSString *)contentType;
- (nullable NSString *)sourceFilename;
- (nullable UIImage *)thumbnailImage;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
attachmentStream:(nullable TSAttachmentStream *)attachment;
- (TSQuotedMessage *)buildQuotedMessage;
@end
@interface OWSAttachmentInfo: MTLModel
@ -47,15 +76,10 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initOutgoingWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
attachment:(TSAttachmentStream *_Nullable)attachmentStream;
- (instancetype)initIncomingWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
attachments:(NSArray<TSAttachment *> *)attachments;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
attachments:(NSArray<TSAttachment *> *)attachments;
@end

View file

@ -31,11 +31,46 @@ NS_ASSUME_NONNULL_BEGIN
@end
@implementation OWSQuotedReplyDraft
// This is a MIME type.
//
// This property should be set IFF we are quoting an attachment message.
- (nullable NSString *)contentType
{
return self.attachmentStream.contentType;
}
- (nullable NSString *)sourceFilename
{
return self.attachmentStream.sourceFilename;
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
attachmentStream:(nullable TSAttachmentStream *)attachmentStream
{
self = [super init];
if (!self) {
return self;
}
_timestamp = timestamp;
_authorId = authorId;
_body = body;
_attachmentStream = attachmentStream;
return self;
}
@end
@interface TSQuotedMessage ()
@property (atomic) NSArray<OWSAttachmentInfo *> *thumbnailAttachments;
@end
@implementation TSQuotedMessage
@ -134,10 +169,10 @@ NS_ASSUME_NONNULL_BEGIN
return self.thumbnailAttachments.firstObject;
}
- (TSAttachmentStream *)thumbnailAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction
{
}
//- (TSAttachmentStream *)thumbnailAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction
//{
//
//}
- (void)createThumbnailAttachmentIfNecessaryWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{

View file

@ -1113,7 +1113,7 @@ NS_ASSUME_NONNULL_BEGIN
attachments = attachmentsProcessor.supportedAttachmentPointers;
}
// TODO
// TODO - but only if the attachment can't be found locally.
// [attachmentsProcessor fetchAttachmentsForMessage:nil
// transaction:transaction
// success:^(TSAttachmentStream *attachmentStream) {
@ -1142,10 +1142,8 @@ NS_ASSUME_NONNULL_BEGIN
// sourceFilename:sourceFilename
// thumbnailData:thumbnailData
// contentType:contentType];
TSQuotedMessage *quotedMessage = [[TSQuotedMessage alloc] initIncomingWithTimestamp:timestamp
authorId:authorId
body:body
attachments:attachments];
TSQuotedMessage *quotedMessage =
[[TSQuotedMessage alloc] initWithTimestamp:timestamp authorId:authorId body:body attachments:attachments];
return quotedMessage;
}

View file

@ -324,27 +324,28 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
[sendingQueue addOperation:uploadAttachmentOperation];
}
if (message.quotedMessage) {
// TODO do we want a different thumbnail size for quotes vs the gallery? This seems reasonable,
// and has the advantage of already having been generated.
__block TSAttachmentStream *attachment;
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[message.quotedMessage createThumbnailAttachmentIfNecessaryWithTransaction:transaction];
attachment = (TSAttachmentStream *)[message.quotedMessage thumbnailAttachmentWithTransaction:transaction];
}];
if (attachment) {
OWSUploadOperation *uploadQuoteThumbnailOperation =
[[OWSUploadOperation alloc] initWithAttachmentId:thumbnailAttachment.uniqueId
dbConnection:self.dbConnection];
// TODO put attachment uploads on a (lowly) concurrent queue
[sendMessageOperation addDependency:uploadQuoteThumbnailOperation];
[sendingQueue addOperation:uploadQuoteThumbnailOperation];
}
}
//
// if (message.quotedMessage) {
//
// // TODO do we want a different thumbnail size for quotes vs the gallery? This seems reasonable,
// // and has the advantage of already having been generated.
// __block TSAttachmentStream *attachment;
// [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
// [message.quotedMessage createThumbnailAttachmentIfNecessaryWithTransaction:transaction];
// attachment = (TSAttachmentStream *)[message.quotedMessage
// thumbnailAttachmentWithTransaction:transaction];
// }];
//
// if (attachment) {
// OWSUploadOperation *uploadQuoteThumbnailOperation =
// [[OWSUploadOperation alloc] initWithAttachmentId:thumbnailAttachment.uniqueId
// dbConnection:self.dbConnection];
//
// // TODO put attachment uploads on a (lowly) concurrent queue
// [sendMessageOperation addDependency:uploadQuoteThumbnailOperation];
// [sendingQueue addOperation:uploadQuoteThumbnailOperation];
// }
// }
[sendingQueue addOperation:sendMessageOperation];
});

View file

@ -4,8 +4,8 @@
NS_ASSUME_NONNULL_BEGIN
@class OWSQuotedReplyDraft;
@class TSMessage;
@class TSQuotedMessage;
@class TSThread;
@class YapDatabaseReadTransaction;
@ -20,8 +20,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateApplicationBadgeCount;
+ (nullable TSQuotedMessage *)quotedMessageForMessage:(TSMessage *)message
transaction:(YapDatabaseReadTransaction *)transaction;
+ (nullable OWSQuotedReplyDraft *)quotedReplyDraftForMessage:(TSMessage *)message
transaction:(YapDatabaseReadTransaction *)transaction;
@end

View file

@ -104,8 +104,8 @@ NS_ASSUME_NONNULL_BEGIN
return numberOfItems;
}
+ (nullable TSQuotedMessage *)quotedMessageForMessage:(TSMessage *)message
transaction:(YapDatabaseReadTransaction *)transaction;
+ (nullable OWSQuotedReplyDraft *)quotedReplyDraftForMessage:(TSMessage *)message
transaction:(YapDatabaseReadTransaction *)transaction;
{
OWSAssert(message);
OWSAssert(transaction);
@ -124,13 +124,13 @@ NS_ASSUME_NONNULL_BEGIN
}();
OWSAssert(authorId.length > 0);
return [self quotedMessageForMessage:message authorId:authorId thread:thread transaction:transaction];
return [self quotedReplyDraftForMessage:message authorId:authorId thread:thread transaction:transaction];
}
+ (nullable TSQuotedMessage *)quotedMessageForMessage:(TSMessage *)message
authorId:(NSString *)authorId
thread:(TSThread *)thread
transaction:(YapDatabaseReadTransaction *)transaction
+ (nullable OWSQuotedReplyDraft *)quotedReplyDraftForMessage:(TSMessage *)message
authorId:(NSString *)authorId
thread:(TSThread *)thread
transaction:(YapDatabaseReadTransaction *)transaction
{
OWSAssert(message);
OWSAssert(authorId.length > 0);
@ -198,11 +198,10 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
TSQuotedMessage *quotedMessage = [[TSQuotedMessage alloc] initOutgoingWithTimestamp:timestamp
authorId:authorId
body:quotedText
attachment:quotedAttachment];
return quotedMessage;
return [[OWSQuotedReplyDraft alloc] initWithTimestamp:timestamp
authorId:authorId
body:quotedText
attachmentStream:quotedAttachment];
}
+ (nullable NSData *)thumbnailDataForAttachment:(TSAttachment *)attachment