Rework proto schema changes for quoted replies.

Sketch out model changes for quoted replies.

Sketch out quoted reply input preview.

Send quoted messages protos.

Update models to reflect quoted messages.

Rework interaction initializers.

Rework interaction initializers.

Add debug UI methods for generating quoted reply variations.

Add debug UI methods for generating quoted reply variations.
This commit is contained in:
Matthew Chen 2018-02-07 09:44:09 -08:00 committed by Matthew Chen
parent 308fa59973
commit 8e4f2ca0ed
62 changed files with 2278 additions and 858 deletions

View file

@ -111,7 +111,6 @@
346129C71FD2072E00532771 /* NSString+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129C01FD2072C00532771 /* NSString+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
346129C81FD2072E00532771 /* NSAttributedString+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129C11FD2072D00532771 /* NSAttributedString+OWS.m */; };
346129C91FD2072E00532771 /* NSString+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129C21FD2072D00532771 /* NSString+OWS.m */; };
346129CA1FD2072E00532771 /* UIImage+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129C31FD2072D00532771 /* UIImage+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
346129CB1FD2072E00532771 /* Promise+retainUntilComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346129C41FD2072D00532771 /* Promise+retainUntilComplete.swift */; };
346129CC1FD2072E00532771 /* NSAttributedString+OWS.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129C51FD2072D00532771 /* NSAttributedString+OWS.h */; settings = {ATTRIBUTES = (Public, ); }; };
346129CD1FD2072E00532771 /* UIImage+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129C61FD2072D00532771 /* UIImage+OWS.m */; };
@ -684,10 +683,8 @@
346129C01FD2072C00532771 /* NSString+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+OWS.h"; sourceTree = "<group>"; };
346129C11FD2072D00532771 /* NSAttributedString+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributedString+OWS.m"; sourceTree = "<group>"; };
346129C21FD2072D00532771 /* NSString+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+OWS.m"; sourceTree = "<group>"; };
346129C31FD2072D00532771 /* UIImage+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+OWS.h"; sourceTree = "<group>"; };
346129C41FD2072D00532771 /* Promise+retainUntilComplete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+retainUntilComplete.swift"; sourceTree = "<group>"; };
346129C51FD2072D00532771 /* NSAttributedString+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributedString+OWS.h"; sourceTree = "<group>"; };
346129C61FD2072D00532771 /* UIImage+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+OWS.m"; sourceTree = "<group>"; };
346129CF1FD207F200532771 /* OWSAlerts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAlerts.swift; sourceTree = "<group>"; };
346129D11FD2085A00532771 /* CommonStrings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonStrings.swift; sourceTree = "<group>"; };
346129D31FD20ADB00532771 /* UIViewController+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+OWS.m"; sourceTree = "<group>"; };
@ -1407,8 +1404,6 @@
34480B5E1FD0A98800BC14EF /* UIColor+OWS.m */,
34480B661FD0AA9400BC14EF /* UIFont+OWS.h */,
34480B651FD0AA9400BC14EF /* UIFont+OWS.m */,
346129C31FD2072D00532771 /* UIImage+OWS.h */,
346129C61FD2072D00532771 /* UIImage+OWS.m */,
34480B5F1FD0A98800BC14EF /* UIView+OWS.h */,
34480B601FD0A98800BC14EF /* UIView+OWS.m */,
346129D41FD20ADC00532771 /* UIViewController+OWS.h */,
@ -3072,7 +3067,6 @@
347850591FD9972E007B8332 /* SwiftSingletons.swift in Sources */,
344F248720069ECB00CFB4F4 /* ModalActivityIndicatorViewController.swift in Sources */,
346129961FD1E30000532771 /* OWSDatabaseMigration.m in Sources */,
346129CD1FD2072E00532771 /* UIImage+OWS.m in Sources */,
344D6CEC20069E070042AF96 /* NewNonContactConversationViewController.m in Sources */,
346129FB1FD5F31400532771 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */,
344F248D2007CCD600CFB4F4 /* DisplayableText.swift in Sources */,

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "quoted-message-cancel@1x.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "quoted-message-cancel@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "quoted-message-cancel@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -62,7 +62,6 @@
#import <SignalMessaging/ThreadUtil.h>
#import <SignalMessaging/UIColor+OWS.h>
#import <SignalMessaging/UIFont+OWS.h>
#import <SignalMessaging/UIImage+OWS.h>
#import <SignalMessaging/UIUtil.h>
#import <SignalMessaging/UIView+OWS.h>
#import <SignalMessaging/UIViewController+OWS.h>
@ -126,6 +125,7 @@
#import <SignalServiceKit/TSSocketManager.h>
#import <SignalServiceKit/TSThread.h>
#import <SignalServiceKit/Threading.h>
#import <SignalServiceKit/UIImage+OWS.h>
#import <WebRTC/RTCAudioSession.h>
#import <WebRTC/RTCCameraPreviewView.h>
#import <YYImage/YYImage.h>

View file

@ -5,6 +5,7 @@
NS_ASSUME_NONNULL_BEGIN
@class SignalAttachment;
@class TSQuotedMessage;
@protocol ConversationInputToolbarDelegate <NSObject>
@ -57,6 +58,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)cancelVoiceMemoIfNecessary;
- (void)setQuotedMessage:(TSQuotedMessage *)quotedMessage;
- (void)clearQuotedMessage;
@end
NS_ASSUME_NONNULL_END

View file

@ -4,6 +4,8 @@
#import "ConversationInputToolbar.h"
#import "ConversationInputTextView.h"
#import "Environment.h"
#import "OWSContactsManager.h"
#import "OWSMath.h"
#import "Signal-Swift.h"
#import "UIColor+OWS.h"
@ -12,11 +14,104 @@
#import "ViewControllerUtils.h"
#import <SignalMessaging/OWSFormat.h>
#import <SignalServiceKit/NSTimer+OWS.h>
#import <SignalServiceKit/TSQuotedMessage.h>
NS_ASSUME_NONNULL_BEGIN
static void *kConversationInputTextViewObservingContext = &kConversationInputTextViewObservingContext;
static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
@interface QuotedMessagePreviewView : UIView
@property (nonatomic, readonly) UILabel *titleLabel;
@property (nonatomic, readonly) UILabel *bodyLabel;
@property (nonatomic, readonly) UIImageView *iconView;
@property (nonatomic, readonly) UIButton *cancelButton;
@property (nonatomic, readonly) UIView *quoteStripe;
@end
@implementation QuotedMessagePreviewView
- (nullable UIImageView *)iconForMessage:(TSQuotedMessage *)message
{
// FIXME TODO
return nil;
}
- (instancetype)initWithQuotedMessage:(TSQuotedMessage *)message
{
self = [super initWithFrame:CGRectZero];
if (!self) {
return self;
}
_titleLabel = [UILabel new];
_titleLabel.text = [[Environment current].contactsManager displayNameForPhoneIdentifier:message.authorId];
_bodyLabel = [UILabel new];
_bodyLabel.text = message.body;
_iconView = [self iconForMessage:message];
if (_iconView) {
[self addSubview:_iconView];
}
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *buttonImage =
[[UIImage imageNamed:@"quoted-message-cancel"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[_cancelButton setImage:buttonImage forState:UIControlStateNormal];
_cancelButton.imageView.tintColor = [UIColor ows_blackColor];
_quoteStripe = [UIView new];
BOOL isQuotingSelf = [message.authorId isEqualToString:[TSAccountManager localNumber]];
// FIXME actual colors TBD
_quoteStripe.backgroundColor = isQuotingSelf ? [UIColor orangeColor] : [UIColor blackColor];
UIView *contentContainer = [UIView containerView];
[self addSubview:_titleLabel];
[self addSubview:contentContainer];
[contentContainer addSubview:_bodyLabel];
[self addSubview:_cancelButton];
[self addSubview:_quoteStripe];
// Layout
CGFloat kLeadingMargin = 4;
[_quoteStripe autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeRight];
[_titleLabel autoPinEdgeToSuperviewEdge:ALEdgeTop];
[_titleLabel autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:_quoteStripe withOffset:kLeadingMargin];
[_titleLabel autoPinEdge:ALEdgeTrailing toEdge:ALEdgeLeading ofView:_cancelButton];
if (_iconView) {
[contentContainer addSubview:_iconView];
[_iconView autoPinEdgeToSuperviewEdge:ALEdgeLeading];
[_iconView autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:_bodyLabel];
[_iconView autoPinHeightToSuperview];
} else {
[_bodyLabel autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:_quoteStripe withOffset:kLeadingMargin];
}
[_bodyLabel autoPinHeightToSuperview];
[_bodyLabel autoPinEdgeToSuperviewEdge:ALEdgeTrailing];
[contentContainer autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_titleLabel];
[contentContainer autoPinEdge:ALEdgeTrailing toEdge:ALEdgeLeading ofView:_cancelButton];
[contentContainer autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[_cancelButton autoPinEdgeToSuperviewEdge:ALEdgeTop];
[_cancelButton autoVCenterInSuperview];
return self;
}
@end
#pragma mark -
@interface ConversationInputToolbar () <UIGestureRecognizerDelegate, ConversationTextViewToolbarDelegate>
@property (nonatomic, readonly) UIView *contentView;
@ -34,6 +129,10 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
@property (nonatomic) CGFloat toolbarHeight;
@property (nonatomic) CGFloat textViewHeight;
#pragma mark -
@property (nonatomic, nullable) QuotedMessagePreviewView *quotedMessageView;
#pragma mark - Voice Memo Recording UI
@property (nonatomic, nullable) UIView *voiceMemoUI;
@ -46,6 +145,9 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
@end
#pragma mark -
#pragma mark -
@implementation ConversationInputToolbar
@ -226,6 +328,18 @@ static const CGFloat ConversationInputToolbarBorderViewHeight = 0.5;
[self ensureContentConstraints];
}
- (void)setQuotedMessage:(TSQuotedMessage *)quotedMessage
{
QuotedMessagePreviewView *quotedMessageView =
[[QuotedMessagePreviewView alloc] initWithQuotedMessage:quotedMessage];
[self ensureContentConstraints];
}
- (void)clearQuotedMessage
{
}
- (void)beginEditingTextMessage
{
[self.inputTextView becomeFirstResponder];

View file

@ -3549,9 +3549,15 @@ typedef enum : NSUInteger {
groupThread.groupModel = newGroupModel;
[groupThread saveWithTransaction:transaction];
message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:groupThread
groupMetaMessage:TSGroupMessageUpdate];
message = [[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:groupThread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUpdate
quotedMessage:nil];
[message updateWithCustomMessage:updateGroupInfo transaction:transaction];
}];

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,6 @@
#import <AxolotlKit/PreKeyBundle.h>
#import <SignalMessaging/AttachmentSharing.h>
#import <SignalMessaging/Environment.h>
#import <SignalMessaging/UIImage+OWS.h>
#import <SignalServiceKit/OWSDisappearingConfigurationUpdateInfoMessage.h>
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
#import <SignalServiceKit/OWSPrimaryStorage+SessionStore.h>
@ -21,6 +20,7 @@
#import <SignalServiceKit/TSCall.h>
#import <SignalServiceKit/TSInvalidIdentityKeyReceivingErrorMessage.h>
#import <SignalServiceKit/TSThread.h>
#import <SignalServiceKit/UIImage+OWS.h>
NS_ASSUME_NONNULL_BEGIN

View file

@ -683,9 +683,16 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:removingFromGroup animated:YES completion:nil];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
groupMetaMessage:TSGroupMessageQuit];
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageQuit
quotedMessage:nil];
[self.messageSender enqueueMessage:message
success:^{
[self dismissViewControllerAnimated:YES

View file

@ -490,9 +490,15 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
canCancel:NO
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
groupMetaMessage:TSGroupMessageNew];
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNew
quotedMessage:nil];
[message updateWithCustomMessage:NSLocalizedString(@"GROUP_CREATED", nil)];

View file

@ -936,9 +936,16 @@ NS_ASSUME_NONNULL_BEGIN
- (void)leaveGroup
{
TSGroupThread *gThread = (TSGroupThread *)self.thread;
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:gThread
groupMetaMessage:TSGroupMessageQuit];
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:gThread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageQuit
quotedMessage:nil];
[self.messageSender enqueueMessage:message
success:^{
DDLogInfo(@"%@ Successfully left group.", self.logTag);

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalServiceKit/TSInteraction.h>
@ -13,14 +13,16 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) BOOL hasAddToProfileWhitelistOffer;
@property (nonatomic, readonly) NSString *recipientId;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
recipientId:(NSString *)recipientId NS_DESIGNATED_INITIALIZER;
- (instancetype)initContactOffersWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
recipientId:(NSString *)recipientId NS_DESIGNATED_INITIALIZER;
@end

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSContactOffersInteraction.h"
@ -13,14 +13,14 @@ NS_ASSUME_NONNULL_BEGIN
return [super initWithCoder:coder];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
recipientId:(NSString *)recipientId
- (instancetype)initContactOffersWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasBlockOffer:(BOOL)hasBlockOffer
hasAddToContactsOffer:(BOOL)hasAddToContactsOffer
hasAddToProfileWhitelistOffer:(BOOL)hasAddToProfileWhitelistOffer
recipientId:(NSString *)recipientId
{
self = [super initWithTimestamp:timestamp inThread:thread];
self = [super initInteractionWithTimestamp:timestamp inThread:thread];
if (!self) {
return self;

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalServiceKit/TSInteraction.h>
@ -12,12 +12,15 @@ NS_ASSUME_NONNULL_BEGIN
@property (atomic, readonly) NSUInteger missingUnseenSafetyNumberChangeCount;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount NS_DESIGNATED_INITIALIZER;
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
NS_DESIGNATED_INITIALIZER;
@end

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSUnreadIndicatorInteraction.h"
@ -21,12 +21,12 @@ NS_ASSUME_NONNULL_BEGIN
return [super initWithCoder:coder];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
- (instancetype)initUnreadIndicatorWithTimestamp:(uint64_t)timestamp
thread:(TSThread *)thread
hasMoreUnseenMessages:(BOOL)hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:(NSUInteger)missingUnseenSafetyNumberChangeCount
{
self = [super initWithTimestamp:timestamp inThread:thread];
self = [super initInteractionWithTimestamp:timestamp inThread:thread];
if (!self) {
return self;

View file

@ -40,9 +40,9 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
#import <SignalMessaging/ThreadUtil.h>
#import <SignalMessaging/UIColor+OWS.h>
#import <SignalMessaging/UIFont+OWS.h>
#import <SignalMessaging/UIImage+OWS.h>
#import <SignalMessaging/UIUtil.h>
#import <SignalMessaging/UIView+OWS.h>
#import <SignalMessaging/UIViewController+OWS.h>
#import <SignalMessaging/VersionMigrations.h>
#import <SignalMessaging/ViewControllerUtils.h>
#import <SignalServiceKit/UIImage+OWS.h>

View file

@ -6,7 +6,6 @@
#import "Environment.h"
#import "NSString+OWS.h"
#import "OWSUserProfile.h"
#import "UIImage+OWS.h"
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalServiceKit/AppContext.h>
#import <SignalServiceKit/Cryptography.h>
@ -28,6 +27,7 @@
#import <SignalServiceKit/TSThread.h>
#import <SignalServiceKit/TSYapDatabaseObject.h>
#import <SignalServiceKit/TextSecureKitEnv.h>
#import <SignalServiceKit/UIImage+OWS.h>
NS_ASSUME_NONNULL_BEGIN

View file

@ -82,12 +82,15 @@ NS_ASSUME_NONNULL_BEGIN
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:text
attachmentIds:[NSMutableArray new]
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc]
initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:text
attachmentIds:[NSMutableArray new]
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
[messageSender enqueueMessage:message success:successHandler failure:failureHandler];
@ -121,13 +124,16 @@ NS_ASSUME_NONNULL_BEGIN
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:attachment.captionText
isVoiceMessage:[attachment isVoiceMessage]
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc]
initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:attachment.captionText
attachmentIds:[NSMutableArray new]
expiresInSeconds:(configuration.isEnabled ? configuration.durationSeconds : 0)expireStartedAt:0
isVoiceMessage:[attachment isVoiceMessage]
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
[messageSender enqueueAttachment:attachment.dataSource
contentType:attachment.mimeType
sourceFilename:attachment.filenameOrDefault
@ -499,12 +505,12 @@ NS_ASSUME_NONNULL_BEGIN
NSString *recipientId = ((TSContactThread *)thread).contactIdentifier;
TSInteraction *offersMessage =
[[OWSContactOffersInteraction alloc] initWithTimestamp:contactOffersTimestamp
thread:thread
hasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
recipientId:recipientId];
[[OWSContactOffersInteraction alloc] initContactOffersWithTimestamp:contactOffersTimestamp
thread:thread
hasBlockOffer:shouldHaveBlockOffer
hasAddToContactsOffer:shouldHaveAddToContactsOffer
hasAddToProfileWhitelistOffer:shouldHaveAddToProfileWhitelistOffer
recipientId:recipientId];
[offersMessage saveWithTransaction:transaction];
DDLogInfo(@"%@ Creating contact offers: %@ (%llu)",
@ -540,11 +546,11 @@ NS_ASSUME_NONNULL_BEGIN
[existingUnreadIndicator removeWithTransaction:transaction];
}
TSUnreadIndicatorInteraction *indicator =
[[TSUnreadIndicatorInteraction alloc] initWithTimestamp:indicatorTimestamp
thread:thread
hasMoreUnseenMessages:result.hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount];
TSUnreadIndicatorInteraction *indicator = [[TSUnreadIndicatorInteraction alloc]
initUnreadIndicatorWithTimestamp:indicatorTimestamp
thread:thread
hasMoreUnseenMessages:result.hasMoreUnseenMessages
missingUnseenSafetyNumberChangeCount:missingUnseenSafetyNumberChangeCount];
[indicator saveWithTransaction:transaction];
DDLogInfo(@"%@ Creating TSUnreadIndicatorInteraction: %@ (%llu)",

View file

@ -1,11 +1,11 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIImage+OWS.h"
#import <SignalServiceKit/MIMETypeUtil.h>
#import <SignalServiceKit/UIImage+OWS.h>
typedef void (^completionBlock)(void);

View file

@ -87,6 +87,14 @@ message DataMessage {
PROFILE_KEY_UPDATE = 4;
}
message Quote
{
optional uint64 id = 1;
optional string author = 2;
optional string text = 3;
optional AttachmentPointer attachment = 4;
}
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
@ -94,6 +102,7 @@ message DataMessage {
optional uint32 expireTimer = 5;
optional bytes profileKey = 6;
optional uint64 timestamp = 7;
optional Quote quote = 8;
}
message NullMessage {

View file

@ -15,11 +15,21 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark -
@implementation OWSReadReceiptsForSenderMessage
- (instancetype)initWithThread:(nullable TSThread *)thread messageTimestamps:(NSArray<NSNumber *> *)messageTimestamps
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -88,12 +88,15 @@ NS_ASSUME_NONNULL_BEGIN
// TODO group updates. Currently desktop doesn't support group updates, so not a problem yet.
TSOutgoingMessage *outgoingMessage =
[[TSOutgoingMessage alloc] initWithTimestamp:transcript.timestamp
inThread:thread
messageBody:transcript.body
attachmentIds:[attachmentsProcessor.attachmentIds mutableCopy]
expiresInSeconds:transcript.expirationDuration
expireStartedAt:transcript.expirationStartedAt];
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:transcript.timestamp
inThread:thread
messageBody:transcript.body
attachmentIds:[attachmentsProcessor.attachmentIds mutableCopy]
expiresInSeconds:transcript.expirationDuration
expireStartedAt:transcript.expirationStartedAt
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (transcript.isExpirationTimerUpdate) {
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:outgoingMessage

View file

@ -180,6 +180,8 @@ NSUInteger const TSAttachmentSchemaVersion = 4;
}
} else if ([MIMETypeUtil isAnimated:self.contentType]) {
return [NSString stringWithFormat:@"🎡 %@", attachmentString];
} else {
return [NSString stringWithFormat:@"📎 %@", attachmentString];
}
return attachmentString;

View file

@ -14,7 +14,16 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:nil
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSSyncContactsMessage.h"
@ -30,7 +30,15 @@ NS_ASSUME_NONNULL_BEGIN
identityManager:(OWSIdentityManager *)identityManager
profileManager:(id<ProfileManagerProtocol>)profileManager
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:nil
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -16,7 +16,15 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init
{
return [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
return [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:nil
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder

View file

@ -20,7 +20,15 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithThread:(nullable TSThread *)thread groupId:(NSData *)groupId
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -15,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark -
@implementation OWSDisappearingMessagesConfigurationMessage
- (BOOL)shouldBeSaved
@ -24,7 +26,15 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithConfiguration:(OWSDisappearingMessagesConfiguration *)configuration thread:(TSThread *)thread
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSDynamicOutgoingMessage.h"
@ -27,7 +27,15 @@ NS_ASSUME_NONNULL_BEGIN
timestamp:(uint64_t)timestamp
thread:(nullable TSThread *)thread
{
self = [super initWithTimestamp:timestamp inThread:thread];
self = [super initOutgoingMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (self) {
_block = block;

View file

@ -1,5 +1,6 @@
// Created by Michael Kirk on 11/3/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSOutgoingMessage.h"
@ -8,6 +9,8 @@ NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(EndSessionMessage)
@interface OWSEndSessionMessage : TSOutgoingMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View file

@ -9,6 +9,19 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSEndSessionMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread
{
return [super initOutgoingMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
}
- (BOOL)shouldBeSaved
{
return NO;

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSReadTracking.h"
@ -8,12 +8,10 @@
NS_ASSUME_NONNULL_BEGIN
@interface TSErrorMessage : TSMessage <OWSReadTracking>
typedef NS_ENUM(int32_t, TSErrorMessageType) {
TSErrorMessageNoSession,
TSErrorMessageWrongTrustedIdentityKey, // DEPRECATED: We no longer create TSErrorMessageWrongTrustedIdentityKey, but
// persisted legacy messages could exist indefinitly.
// persisted legacy messages could exist indefinitly.
TSErrorMessageInvalidKeyException,
TSErrorMessageMissingKeyId, // unused
TSErrorMessageInvalidMessage,
@ -24,6 +22,16 @@ typedef NS_ENUM(int32_t, TSErrorMessageType) {
TSErrorMessageGroupCreationFailed,
};
@interface TSErrorMessage : TSMessage <OWSReadTracking>
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimestamp:(uint64_t)timestamp

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSErrorMessage.h"
@ -59,12 +59,13 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
failedMessageType:(TSErrorMessageType)errorMessageType
recipientId:(nullable NSString *)recipientId
{
self = [super initWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0];
self = [super initMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0
quotedMessage:nil];
if (!self) {
return self;

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSReadTracking.h"
@ -12,27 +12,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface TSIncomingMessage : TSMessage <OWSReadTracking>
/**
* Inits an incoming group message without attachments
*
* @param timestamp
* When the message was created in milliseconds since epoch
* @param thread
* Thread to which the message belongs
* @param authorId
* Signal ID (i.e. e164) of the user who sent the message
* @param sourceDeviceId
* Numeric ID of the device used to send the message. Used to detect duplicate messages.
* @param body
* Body of the message
*
* @return initiated incoming group message
*/
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body;
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
/**
* Inits an incoming group message that expires.
@ -51,45 +37,22 @@ NS_ASSUME_NONNULL_BEGIN
* The uniqueIds for the message's attachments, possibly an empty list.
* @param expiresInSeconds
* Seconds from when the message is read until it is deleted.
* @param quotedMessage
* If this message is a quoted reply to another message, contains data about that message.
*
* @return initiated incoming group message
*/
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds NS_DESIGNATED_INITIALIZER;
- (instancetype)initIncomingMessageWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
/**
* For sake of a smaller API, and simplifying assumptions elsewhere, you must specify an author id for *all* incoming
* messages, even though we technically could infer the author id for a contact thread.
*/
- (instancetype)initWithTimestamp:(uint64_t)timestamp NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt NS_UNAVAILABLE;
/*
* Find a message matching the senderId and timestamp, if any.
*

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSIncomingMessage.h"
@ -35,35 +35,22 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body
- (instancetype)initIncomingMessageWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
{
return [self initWithTimestamp:timestamp
inThread:thread
authorId:authorId
sourceDeviceId:sourceDeviceId
messageBody:body
attachmentIds:@[]
expiresInSeconds:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
authorId:(NSString *)authorId
sourceDeviceId:(uint32_t)sourceDeviceId
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
{
self = [super initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:0];
self = [super initMessageWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:0
quotedMessage:quotedMessage];
if (!self) {
return self;

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSReadTracking.h"
@ -28,6 +28,14 @@ typedef NS_ENUM(NSInteger, TSInfoMessageType) {
@property (atomic, readonly) TSInfoMessageType messageType;
@property (atomic, readonly) NSString *customMessage;
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTimestamp:(uint64_t)timestamp

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSInfoMessage.h"
@ -46,12 +46,13 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
inThread:(TSThread *)thread
messageType:(TSInfoMessageType)infoMessage
{
self = [super initWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0];
self = [super initMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:@[]
expiresInSeconds:0
expireStartedAt:0
quotedMessage:nil];
if (!self) {
return self;

View file

@ -21,7 +21,7 @@ typedef NS_ENUM(NSInteger, OWSInteractionType) {
@interface TSInteraction : TSYapDatabaseObject
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread;
@property (nonatomic, readonly) NSString *uniqueThreadId;
@property (nonatomic, readonly) TSThread *thread;

View file

@ -54,7 +54,7 @@ NS_ASSUME_NONNULL_BEGIN
return @"TSInteraction";
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread
{
OWSAssert(timestamp > 0);

View file

@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
@class TSAttachment;
@class TSQuotedMessage;
@interface TSMessage : TSInteraction
@ -20,32 +21,17 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) uint64_t expireStartedAt;
@property (nonatomic, readonly) uint64_t expiresAt;
@property (nonatomic, readonly) BOOL isExpiringMessage;
@property (nonatomic, readonly, nullable) TSQuotedMessage *quotedMessage;
- (instancetype)initWithTimestamp:(uint64_t)timestamp;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt NS_DESIGNATED_INITIALIZER;
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
static const NSUInteger OWSMessageSchemaVersion = 4;
#pragma mark -
@interface TSMessage ()
@property (nonatomic, nullable) NSString *body;
@ -48,63 +50,23 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
// they were received & decrypted, not by when they were sent.
@property (nonatomic) uint64_t receivedAtTimestamp;
@property (nonatomic, nullable) TSQuotedMessage *quotedMessage;
@end
#pragma mark -
@implementation TSMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
{
return [self initWithTimestamp:timestamp inThread:nil messageBody:nil];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread
{
return [self initWithTimestamp:timestamp inThread:thread messageBody:nil attachmentIds:@[]];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
{
return [self initWithTimestamp:timestamp inThread:thread messageBody:body attachmentIds:@[]];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
{
self = [super initWithTimestamp:timestamp inThread:thread];
self = [super initInteractionWithTimestamp:timestamp inThread:thread];
if (!self) {
return self;
@ -118,6 +80,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
_expireStartedAt = expireStartedAt;
[self updateExpiresAt];
_receivedAtTimestamp = [NSDate ows_millisecondTimeStamp];
_quotedMessage = quotedMessage;
return self;
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSMessage.h"
@ -37,49 +37,23 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage) {
@interface TSOutgoingMessage : TSMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp;
- (instancetype)initMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)messageBody
isVoiceMessage:(BOOL)isVoiceMessage
expiresInSeconds:(uint32_t)expiresInSeconds;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage NS_DESIGNATED_INITIALIZER;
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
isVoiceMessage:(BOOL)isVoiceMessage
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
quotedMessage:(nullable TSQuotedMessage *)quotedMessage NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

View file

@ -11,6 +11,7 @@
#import "TSAttachmentStream.h"
#import "TSContactThread.h"
#import "TSGroupThread.h"
#import "TSQuotedMessage.h"
#import "TextSecureKitEnv.h"
#import <YapDatabase/YapDatabase.h>
#import <YapDatabase/YapDatabaseTransaction.h>
@ -74,117 +75,23 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
return self;
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
- (instancetype)initOutgoingMessageWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
isVoiceMessage:(BOOL)isVoiceMessage
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
quotedMessage:(nullable TSQuotedMessage *)quotedMessage
{
return [self initWithTimestamp:timestamp inThread:nil];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread
{
return [self initWithTimestamp:timestamp inThread:thread messageBody:nil];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:[NSMutableArray new]
expiresInSeconds:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:0];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)messageBody
isVoiceMessage:(BOOL)isVoiceMessage
expiresInSeconds:(uint32_t)expiresInSeconds
{
self = [self initWithTimestamp:timestamp
inThread:thread
messageBody:messageBody
attachmentIds:[NSMutableArray new]
expiresInSeconds:expiresInSeconds
expireStartedAt:0];
if (self) {
_isVoiceMessage = isVoiceMessage;
}
return self;
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
{
TSGroupMetaMessage groupMetaMessage
= ([thread isKindOfClass:[TSGroupThread class]] ? TSGroupMessageDeliver : TSGroupMessageNone);
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:expireStartedAt
groupMetaMessage:groupMetaMessage];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
{
return [self initWithTimestamp:timestamp
inThread:thread
messageBody:@""
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
groupMetaMessage:groupMetaMessage];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(nullable TSThread *)thread
messageBody:(nullable NSString *)body
attachmentIds:(NSMutableArray<NSString *> *)attachmentIds
expiresInSeconds:(uint32_t)expiresInSeconds
expireStartedAt:(uint64_t)expireStartedAt
groupMetaMessage:(TSGroupMetaMessage)groupMetaMessage
{
self = [super initWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:expireStartedAt];
self = [super initMessageWithTimestamp:timestamp
inThread:thread
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:expiresInSeconds
expireStartedAt:expireStartedAt
quotedMessage:quotedMessage];
if (!self) {
return self;
}
@ -193,6 +100,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
_sentRecipients = [NSArray new];
_hasSyncedTranscript = NO;
_groupMetaMessage = groupMetaMessage;
_isVoiceMessage = isVoiceMessage;
_attachmentFilenameMap = [NSMutableDictionary new];
@ -498,6 +406,44 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
OWSSignalServiceProtosDataMessageBuilder *builder = [self dataMessageBuilder];
[builder setTimestamp:self.timestamp];
[builder addLocalProfileKeyIfNecessary:self.thread recipientId:recipientId];
if (self.quotedMessage) {
OWSSignalServiceProtosDataMessageQuoteBuilder *quoteBuilder =
[OWSSignalServiceProtosDataMessageQuoteBuilder new];
[quoteBuilder setId:self.quotedMessage.timestamp];
[quoteBuilder setAuthor:self.quotedMessage.authorId];
BOOL hasQuotedText = NO;
BOOL hasQuotedAttachment = NO;
if (self.quotedMessage.body.length > 0) {
[quoteBuilder setText:self.quotedMessage.body];
hasQuotedText = YES;
}
if (self.quotedMessage.contentType.length > 0) {
OWSSignalServiceProtosAttachmentPointerBuilder *attachmentBuilder =
[OWSSignalServiceProtosAttachmentPointerBuilder new];
if (self.quotedMessage.thumbnailData.length > 0) {
[attachmentBuilder setThumbnail:self.quotedMessage.thumbnailData];
}
if (self.quotedMessage.sourceFilename.length > 0) {
[attachmentBuilder setFileName:self.quotedMessage.sourceFilename];
}
[attachmentBuilder setContentType:self.quotedMessage.contentType];
[quoteBuilder setAttachmentBuilder:attachmentBuilder];
hasQuotedAttachment = YES;
}
if (hasQuotedText || hasQuotedAttachment) {
[builder setQuoteBuilder:quoteBuilder];
} else {
OWSFail(@"%@ Invalid quoted message data.", self.logTag);
}
}
return [builder build];
}

View file

@ -0,0 +1,39 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalServiceKit/TSYapDatabaseObject.h>
NS_ASSUME_NONNULL_BEGIN
@interface TSQuotedMessage : TSYapDatabaseObject
@property (nonatomic, readonly) uint64_t timestamp;
@property (nonatomic, readonly) NSString *authorId;
// This property should be set IFF we are quoting a text message.
@property (nullable, nonatomic, readonly) NSString *body;
// This property should be set IFF we are quoting a attachment message.
@property (nullable, nonatomic, readonly) NSString *sourceFilename;
// This property can be set IFF we are quoting a attachment message, but it is optional.
@property (nullable, nonatomic, readonly) NSData *thumbnailData;
// This is a MIME type.
//
// This property should be set IFF we are quoting a attachment message.
@property (nullable, nonatomic, readonly) NSString *contentType;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
sourceFilename:(NSString *_Nullable)sourceFilename
thumbnailData:(NSData *_Nullable)thumbnailData
contentType:(NSString *_Nullable)contentType;
@end
#pragma mark -
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,38 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSQuotedMessage.h"
NS_ASSUME_NONNULL_BEGIN
@implementation TSQuotedMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp
authorId:(NSString *)authorId
body:(NSString *_Nullable)body
sourceFilename:(NSString *_Nullable)sourceFilename
thumbnailData:(NSData *_Nullable)thumbnailData
contentType:(NSString *_Nullable)contentType
{
self = [super initWithUniqueId:[NSUUID UUID].UUIDString];
if (!self) {
return self;
}
OWSAssert(timestamp > 0);
OWSAssert(authorId.length > 0);
_timestamp = timestamp;
_authorId = authorId;
_body = body;
_sourceFilename = sourceFilename;
_thumbnailData = thumbnailData;
_contentType = contentType;
return self;
}
@end
NS_ASSUME_NONNULL_END

View file

@ -41,6 +41,7 @@
#import "TSInfoMessage.h"
#import "TSNetworkManager.h"
#import "TSOutgoingMessage.h"
#import "TSQuotedMessage.h"
#import "TextSecureKitEnv.h"
#import <YapDatabase/YapDatabase.h>
@ -888,9 +889,16 @@ NS_ASSUME_NONNULL_BEGIN
NSString *updateGroupInfo =
[gThread.groupModel getInfoStringAboutUpdateTo:gThread.groupModel contactsManager:self.contactsManager];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:gThread
groupMetaMessage:TSGroupMessageUpdate];
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:gThread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageUpdate
quotedMessage:nil];
[message updateWithCustomMessage:updateGroupInfo transaction:transaction];
// Only send this group update to the requester.
[message updateWithSingleGroupRecipient:envelope.source transaction:transaction];
@ -993,19 +1001,24 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
TSQuotedMessage *_Nullable quotedMessage = [self quotedMessageForDataMessage:dataMessage];
DDLogDebug(@"%@ incoming message from: %@ for group: %@ with timestamp: %lu",
self.logTag,
envelopeAddress(envelope),
groupId,
(unsigned long)timestamp);
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:oldGroupThread
authorId:envelope.source
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
inThread:oldGroupThread
authorId:envelope.source
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer
quotedMessage:quotedMessage];
[self finalizeIncomingMessage:incomingMessage
thread:oldGroupThread
envelope:envelope
@ -1036,13 +1049,17 @@ NS_ASSUME_NONNULL_BEGIN
transaction:transaction
relay:envelope.relay];
TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
inThread:thread
authorId:[thread contactIdentifier]
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer];
TSQuotedMessage *_Nullable quotedMessage = [self quotedMessageForDataMessage:dataMessage];
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:timestamp
inThread:thread
authorId:[thread contactIdentifier]
sourceDeviceId:envelope.sourceDevice
messageBody:body
attachmentIds:attachmentIds
expiresInSeconds:dataMessage.expireTimer
quotedMessage:quotedMessage];
[self finalizeIncomingMessage:incomingMessage
thread:thread
envelope:envelope
@ -1053,6 +1070,70 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (TSQuotedMessage *_Nullable)quotedMessageForDataMessage:(OWSSignalServiceProtosDataMessage *)dataMessage
{
OWSAssert(dataMessage);
if (!dataMessage.hasQuote) {
return nil;
}
OWSSignalServiceProtosDataMessageQuote *quoteProto = [dataMessage quote];
if (![quoteProto hasId] || [quoteProto id] == 0) {
OWSFail(@"%@ quoted message missing id", self.logTag);
return nil;
}
uint64_t timestamp = [quoteProto id];
if (![quoteProto hasAuthor] || [quoteProto author].length == 0) {
OWSFail(@"%@ quoted message missing author", self.logTag);
return nil;
}
// TODO: We could verify that this is a valid e164 value.
NSString *authorId = [quoteProto author];
NSString *_Nullable body = nil;
BOOL hasText = NO;
BOOL hasAttachment = NO;
if ([quoteProto hasText] && [quoteProto text].length > 0) {
body = [quoteProto text];
hasText = YES;
}
NSString *_Nullable sourceFilename = nil;
NSData *_Nullable thumbnailData = nil;
NSString *_Nullable contentType = nil;
if ([quoteProto hasAttachment]) {
OWSSignalServiceProtosAttachmentPointer *attachmentProto = [quoteProto attachment];
if ([attachmentProto hasContentType] && attachmentProto.contentType.length > 0) {
contentType = attachmentProto.contentType;
if ([attachmentProto hasFileName] && attachmentProto.fileName.length > 0) {
sourceFilename = attachmentProto.fileName;
}
if ([attachmentProto hasThumbnail] && attachmentProto.thumbnail.length > 0) {
thumbnailData = [attachmentProto thumbnail];
}
}
hasAttachment = YES;
}
if (!hasText && !hasAttachment) {
OWSFail(@"%@ quoted message has neither text nor attachment", self.logTag);
return nil;
}
TSQuotedMessage *quotedMessage = [[TSQuotedMessage alloc] initWithTimestamp:timestamp
authorId:authorId
body:body
sourceFilename:sourceFilename
thumbnailData:thumbnailData
contentType:contentType];
return quotedMessage;
}
- (void)finalizeIncomingMessage:(TSIncomingMessage *)incomingMessage
thread:(TSThread *)thread
envelope:(OWSSignalServiceProtosEnvelope *)envelope
@ -1069,8 +1150,6 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert([TSAccountManager isRegistered]);
NSString *localNumber = [TSAccountManager localNumber];
NSString *body = dataMessage.body;
uint64_t timestamp = envelope.timestamp;
if (!thread) {
OWSFail(@"%@ Can't finalize without thread", self.logTag);

View file

@ -1236,13 +1236,14 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
// We want the incoming message to appear after the outgoing message.
TSIncomingMessage *incomingMessage =
[[TSIncomingMessage alloc] initWithTimestamp:(outgoingMessage.timestamp + 1)
inThread:cThread
authorId:[cThread contactIdentifier]
sourceDeviceId:[OWSDevice currentDeviceId]
messageBody:outgoingMessage.body
attachmentIds:attachmentIds
expiresInSeconds:outgoingMessage.expiresInSeconds];
[[TSIncomingMessage alloc] initIncomingMessageWithTimestamp:(outgoingMessage.timestamp + 1)
inThread:cThread
authorId:[cThread contactIdentifier]
sourceDeviceId:[OWSDevice currentDeviceId]
messageBody:outgoingMessage.body
attachmentIds:attachmentIds
expiresInSeconds:outgoingMessage.expiresInSeconds
quotedMessage:outgoingMessage.quotedMessage];
[incomingMessage saveWithTransaction:transaction];
}];
}

View file

@ -4,7 +4,11 @@
NS_ASSUME_NONNULL_BEGIN
@class TSIncomingMessage;
@class TSOutgoingMessage;
@class TSQuotedMessage;
@class TSThread;
@class YapDatabaseReadWriteTransaction;
@interface OWSMessageUtils : NSObject
@ -17,6 +21,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateApplicationBadgeCount;
+ (nullable TSQuotedMessage *)quotedMessageForIncomingMessage:(TSIncomingMessage *)message
transaction:(YapDatabaseReadWriteTransaction *)transaction;
+ (nullable TSQuotedMessage *)quotedMessageForOutgoingMessage:(TSOutgoingMessage *)message
transaction:(YapDatabaseReadWriteTransaction *)transaction;
@end
NS_ASSUME_NONNULL_END

View file

@ -5,8 +5,16 @@
#import "OWSMessageUtils.h"
#import "AppContext.h"
#import "OWSPrimaryStorage.h"
#import "TSAccountManager.h"
#import "TSAttachment.h"
#import "TSAttachmentStream.h"
#import "TSDatabaseView.h"
#import "TSIncomingMessage.h"
#import "TSMessage.h"
#import "TSOutgoingMessage.h"
#import "TSQuotedMessage.h"
#import "TSThread.h"
#import "UIImage+OWS.h"
#import <YapDatabase/YapDatabase.h>
NS_ASSUME_NONNULL_BEGIN
@ -94,6 +102,138 @@ NS_ASSUME_NONNULL_BEGIN
return numberOfItems;
}
+ (nullable TSQuotedMessage *)quotedMessageForIncomingMessage:(TSIncomingMessage *)message
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(message);
OWSAssert(transaction);
return [self quotedMessageForMessage:message
authorId:message.authorId
thread:[message threadWithTransaction:transaction]
transaction:transaction];
}
+ (nullable TSQuotedMessage *)quotedMessageForOutgoingMessage:(TSOutgoingMessage *)message
transaction:(YapDatabaseReadWriteTransaction *)transaction
{
OWSAssert(message);
OWSAssert(transaction);
return [self quotedMessageForMessage:message
authorId:TSAccountManager.localNumber
thread:[message threadWithTransaction:transaction]
transaction:transaction];
}
+ (nullable TSQuotedMessage *)quotedMessageForMessage:(TSMessage *)message
authorId:(NSString *)authorId
thread:(TSThread *)thread
transaction:(YapDatabaseReadTransaction *)transaction
{
OWSAssert(message);
OWSAssert(authorId.length > 0);
OWSAssert(thread);
OWSAssert(transaction);
uint64_t timestamp = message.timestamp;
NSString *_Nullable body = message.body;
BOOL hasText = body.length > 0;
BOOL hasAttachment = NO;
NSString *_Nullable sourceFilename = nil;
NSData *_Nullable thumbnailData = nil;
NSString *_Nullable contentType = nil;
if (message.attachmentIds.count > 0) {
NSString *attachmentId = message.attachmentIds[0];
TSAttachment *_Nullable attachment =
[TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction];
if (attachment) {
sourceFilename = attachment.sourceFilename;
contentType = attachment.contentType;
// Try to generate a thumbnail, if possible.
thumbnailData = [self thumbnailDataForAttachment:attachment];
hasAttachment = YES;
}
}
if (!hasText && !hasAttachment) {
OWSFail(@"%@ quoted message has neither text nor attachment", self.logTag);
return nil;
}
TSQuotedMessage *quotedMessage = [[TSQuotedMessage alloc] initWithTimestamp:timestamp
authorId:authorId
body:body
sourceFilename:sourceFilename
thumbnailData:thumbnailData
contentType:contentType];
return quotedMessage;
}
+ (nullable NSData *)thumbnailDataForAttachment:(TSAttachment *)attachment
{
OWSAssert(attachment);
// Try to generate a thumbnail, if possible.
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
return nil;
}
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment;
UIImage *_Nullable attachmentImage = [attachmentStream image];
if (!attachmentImage) {
return nil;
}
CGSize attachmentImageSizePx;
attachmentImageSizePx.width = CGImageGetWidth(attachmentImage.CGImage);
attachmentImageSizePx.height = CGImageGetHeight(attachmentImage.CGImage);
if (attachmentImageSizePx.width <= 0 || attachmentImageSizePx.height <= 0) {
DDLogError(@"%@ attachment thumbnail has invalid size.", self.logTag);
return nil;
}
const int kMaxThumbnailSizePx = 100;
// Try to resize image to thumbnail if necessary.
if (attachmentImageSizePx.width > kMaxThumbnailSizePx || attachmentImageSizePx.height > kMaxThumbnailSizePx) {
const CGFloat widthFactor = kMaxThumbnailSizePx / attachmentImageSizePx.width;
const CGFloat heightFactor = kMaxThumbnailSizePx / attachmentImageSizePx.height;
const CGFloat scalingFactor = MIN(widthFactor, heightFactor);
const CGFloat scaledWidthPx = (CGFloat)round(attachmentImageSizePx.width * scalingFactor);
const CGFloat scaledHeightPx = (CGFloat)round(attachmentImageSizePx.height * scalingFactor);
if (scaledWidthPx <= 0 || scaledHeightPx <= 0) {
DDLogError(@"%@ can't determined desired size for attachment thumbnail.", self.logTag);
return nil;
}
if (scaledWidthPx > 0 && scaledHeightPx > 0) {
attachmentImage = [attachmentImage resizedImageToSize:CGSizeMake(scaledWidthPx, scaledHeightPx)];
if (!attachmentImage) {
DDLogError(@"%@ attachment thumbnail could not be resized.", self.logTag);
return nil;
}
attachmentImageSizePx.width = CGImageGetWidth(attachmentImage.CGImage);
attachmentImageSizePx.height = CGImageGetHeight(attachmentImage.CGImage);
}
}
if (attachmentImageSizePx.width <= 0 || attachmentImageSizePx.height <= 0) {
DDLogError(@"%@ resized attachment thumbnail has invalid size.", self.logTag);
return nil;
}
NSData *_Nullable attachmentImageData = UIImagePNGRepresentation(attachmentImage);
if (!attachmentImage) {
OWSFail(@"%@ attachment thumbnail could not be written to PNG.", self.logTag);
return nil;
}
return attachmentImageData;
}
@end
NS_ASSUME_NONNULL_END

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSOutgoingCallMessage.h"
@ -18,13 +18,19 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSOutgoingCallMessage
//@synthesize thread = _thread;
- (instancetype)initWithThread:(TSThread *)thread
{
// These records aren't saved, but their timestamp is used in the event
// of a failing message send to insert the error at the appropriate place.
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSOutgoingNullMessage.h"
@ -17,13 +17,22 @@ NS_ASSUME_NONNULL_BEGIN
@end
#pragma mark -
@implementation OWSOutgoingNullMessage
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:contactThread];
self = [super initOutgoingMessageWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:contactThread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
if (!self) {
return self;
}

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSOutgoingMessage.h"
@ -8,6 +8,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSProfileKeyMessage : TSOutgoingMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View file

@ -12,6 +12,19 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSProfileKeyMessage
- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(nullable TSThread *)thread
{
return [super initOutgoingMessageWithTimestamp:timestamp
inThread:thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:0
expireStartedAt:0
isVoiceMessage:NO
groupMetaMessage:TSGroupMessageNone
quotedMessage:nil];
}
- (BOOL)shouldBeSaved
{
return NO;

View file

@ -1,4 +1,6 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <ProtocolBuffers/ProtocolBuffers.h>
@ -26,6 +28,8 @@
@class OWSSignalServiceProtosContentBuilder;
@class OWSSignalServiceProtosDataMessage;
@class OWSSignalServiceProtosDataMessageBuilder;
@class OWSSignalServiceProtosDataMessageQuote;
@class OWSSignalServiceProtosDataMessageQuoteBuilder;
@class OWSSignalServiceProtosEnvelope;
@class OWSSignalServiceProtosEnvelopeBuilder;
@class OWSSignalServiceProtosGroupContext;
@ -101,7 +105,6 @@
@class PBUninterpretedOptionNamePart;
@class PBUninterpretedOptionNamePartBuilder;
typedef NS_ENUM(SInt32, OWSSignalServiceProtosEnvelopeType) {
OWSSignalServiceProtosEnvelopeTypeUnknown = 0,
OWSSignalServiceProtosEnvelopeTypeCiphertext = 1,
@ -800,17 +803,20 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define DataMessage_expireTimer @"expireTimer"
#define DataMessage_profileKey @"profileKey"
#define DataMessage_timestamp @"timestamp"
#define DataMessage_quote @"quote"
@interface OWSSignalServiceProtosDataMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasTimestamp_:1;
BOOL hasBody_:1;
BOOL hasGroup_:1;
BOOL hasQuote_ : 1;
BOOL hasProfileKey_:1;
BOOL hasFlags_:1;
BOOL hasExpireTimer_:1;
UInt64 timestamp;
NSString* body;
OWSSignalServiceProtosGroupContext* group;
OWSSignalServiceProtosDataMessageQuote *quote;
NSData* profileKey;
UInt32 flags;
UInt32 expireTimer;
@ -822,6 +828,7 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (BOOL) hasExpireTimer;
- (BOOL) hasProfileKey;
- (BOOL) hasTimestamp;
- (BOOL)hasQuote;
@property (readonly, strong) NSString* body;
@property (readonly, strong) NSArray<OWSSignalServiceProtosAttachmentPointer*> * attachments;
@property (readonly, strong) OWSSignalServiceProtosGroupContext* group;
@ -829,6 +836,7 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
@property (readonly) UInt32 expireTimer;
@property (readonly, strong) NSData* profileKey;
@property (readonly) UInt64 timestamp;
@property (readonly, strong) OWSSignalServiceProtosDataMessageQuote *quote;
- (OWSSignalServiceProtosAttachmentPointer*)attachmentsAtIndex:(NSUInteger)index;
+ (instancetype) defaultInstance;
@ -849,6 +857,94 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
+ (OWSSignalServiceProtosDataMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
#define Quote_id @"id"
#define Quote_author @"author"
#define Quote_text @"text"
#define Quote_attachment @"attachment"
@interface OWSSignalServiceProtosDataMessageQuote : PBGeneratedMessage <GeneratedMessageProtocol> {
@private
BOOL hasId_ : 1;
BOOL hasAuthor_ : 1;
BOOL hasText_ : 1;
BOOL hasAttachment_ : 1;
UInt64 id;
NSString *author;
NSString *text;
OWSSignalServiceProtosAttachmentPointer *attachment;
}
- (BOOL)hasId;
- (BOOL)hasAuthor;
- (BOOL)hasText;
- (BOOL)hasAttachment;
@property (readonly) UInt64 id;
@property (readonly, strong) NSString *author;
@property (readonly, strong) NSString *text;
@property (readonly, strong) OWSSignalServiceProtosAttachmentPointer *attachment;
+ (instancetype)defaultInstance;
- (instancetype)defaultInstance;
- (BOOL)isInitialized;
- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)builder;
+ (OWSSignalServiceProtosDataMessageQuoteBuilder *)builder;
+ (OWSSignalServiceProtosDataMessageQuoteBuilder *)builderWithPrototype:
(OWSSignalServiceProtosDataMessageQuote *)prototype;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)toBuilder;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromData:(NSData *)data;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromData:(NSData *)data
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromInputStream:(NSInputStream *)input;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromInputStream:(NSInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromCodedInputStream:(PBCodedInputStream *)input;
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromCodedInputStream:(PBCodedInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
@end
@interface OWSSignalServiceProtosDataMessageQuoteBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosDataMessageQuote *resultQuote;
}
- (OWSSignalServiceProtosDataMessageQuote *)defaultInstance;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clear;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clone;
- (OWSSignalServiceProtosDataMessageQuote *)build;
- (OWSSignalServiceProtosDataMessageQuote *)buildPartial;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFrom:(OWSSignalServiceProtosDataMessageQuote *)other;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
- (BOOL)hasId;
- (UInt64)id;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setId:(UInt64)value;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearId;
- (BOOL)hasAuthor;
- (NSString *)author;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAuthor:(NSString *)value;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearAuthor;
- (BOOL)hasText;
- (NSString *)text;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setText:(NSString *)value;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearText;
- (BOOL)hasAttachment;
- (OWSSignalServiceProtosAttachmentPointer *)attachment;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAttachment:(OWSSignalServiceProtosAttachmentPointer *)value;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAttachmentBuilder:
(OWSSignalServiceProtosAttachmentPointerBuilder *)builderForValue;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeAttachment:(OWSSignalServiceProtosAttachmentPointer *)value;
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearAttachment;
@end
@interface OWSSignalServiceProtosDataMessageBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosDataMessage* resultDataMessage;
@ -903,6 +999,14 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (UInt64) timestamp;
- (OWSSignalServiceProtosDataMessageBuilder*) setTimestamp:(UInt64) value;
- (OWSSignalServiceProtosDataMessageBuilder*) clearTimestamp;
- (BOOL)hasQuote;
- (OWSSignalServiceProtosDataMessageQuote *)quote;
- (OWSSignalServiceProtosDataMessageBuilder *)setQuote:(OWSSignalServiceProtosDataMessageQuote *)value;
- (OWSSignalServiceProtosDataMessageBuilder *)setQuoteBuilder:
(OWSSignalServiceProtosDataMessageQuoteBuilder *)builderForValue;
- (OWSSignalServiceProtosDataMessageBuilder *)mergeQuote:(OWSSignalServiceProtosDataMessageQuote *)value;
- (OWSSignalServiceProtosDataMessageBuilder *)clearQuote;
@end
#define NullMessage_padding @"padding"

View file

@ -1,6 +1,9 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSSignalServiceProtos.pb.h"
// @@protoc_insertion_point(imports)
@implementation OWSSignalServiceProtosOwssignalServiceProtosRoot
@ -2922,6 +2925,7 @@ static OWSSignalServiceProtosCallMessageHangup* defaultOWSSignalServiceProtosCal
@property UInt32 expireTimer;
@property (strong) NSData* profileKey;
@property UInt64 timestamp;
@property (strong) OWSSignalServiceProtosDataMessageQuote *quote;
@end
@implementation OWSSignalServiceProtosDataMessage
@ -2970,6 +2974,15 @@ static OWSSignalServiceProtosCallMessageHangup* defaultOWSSignalServiceProtosCal
hasTimestamp_ = !!_value_;
}
@synthesize timestamp;
- (BOOL)hasQuote
{
return !!hasQuote_;
}
- (void)setHasQuote:(BOOL)_value_
{
hasQuote_ = !!_value_;
}
@synthesize quote;
- (instancetype) init {
if ((self = [super init])) {
self.body = @"";
@ -2978,6 +2991,7 @@ static OWSSignalServiceProtosCallMessageHangup* defaultOWSSignalServiceProtosCal
self.expireTimer = 0;
self.profileKey = [NSData data];
self.timestamp = 0L;
self.quote = [OWSSignalServiceProtosDataMessageQuote defaultInstance];
}
return self;
}
@ -3024,6 +3038,9 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
if (self.hasTimestamp) {
[output writeUInt64:7 value:self.timestamp];
}
if (self.hasQuote) {
[output writeMessage:8 value:self.quote];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32) serializedSize {
@ -3054,6 +3071,9 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
if (self.hasTimestamp) {
size_ += computeUInt64Size(7, self.timestamp);
}
if (self.hasQuote) {
size_ += computeMessageSize(8, self.quote);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
@ -3116,6 +3136,11 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
if (self.hasTimestamp) {
[output appendFormat:@"%@%@: %@\n", indent, @"timestamp", [NSNumber numberWithLongLong:self.timestamp]];
}
if (self.hasQuote) {
[output appendFormat:@"%@%@ {\n", indent, @"quote"];
[self.quote writeDescriptionTo:output withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void) storeInDictionary:(NSMutableDictionary *)dictionary {
@ -3144,6 +3169,11 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
if (self.hasTimestamp) {
[dictionary setObject: [NSNumber numberWithLongLong:self.timestamp] forKey: @"timestamp"];
}
if (self.hasQuote) {
NSMutableDictionary *messageDictionary = [NSMutableDictionary dictionary];
[self.quote storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"quote"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL) isEqual:(id)other {
@ -3154,21 +3184,18 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
return NO;
}
OWSSignalServiceProtosDataMessage *otherMessage = other;
return
self.hasBody == otherMessage.hasBody &&
(!self.hasBody || [self.body isEqual:otherMessage.body]) &&
[self.attachmentsArray isEqualToArray:otherMessage.attachmentsArray] &&
self.hasGroup == otherMessage.hasGroup &&
(!self.hasGroup || [self.group isEqual:otherMessage.group]) &&
self.hasFlags == otherMessage.hasFlags &&
(!self.hasFlags || self.flags == otherMessage.flags) &&
self.hasExpireTimer == otherMessage.hasExpireTimer &&
(!self.hasExpireTimer || self.expireTimer == otherMessage.expireTimer) &&
self.hasProfileKey == otherMessage.hasProfileKey &&
(!self.hasProfileKey || [self.profileKey isEqual:otherMessage.profileKey]) &&
self.hasTimestamp == otherMessage.hasTimestamp &&
(!self.hasTimestamp || self.timestamp == otherMessage.timestamp) &&
(self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
return self.hasBody == otherMessage.hasBody && (!self.hasBody || [self.body isEqual:otherMessage.body]) &&
[self.attachmentsArray isEqualToArray:otherMessage.attachmentsArray] && self.hasGroup == otherMessage.hasGroup
&& (!self.hasGroup || [self.group isEqual:otherMessage.group]) && self.hasFlags == otherMessage.hasFlags
&& (!self.hasFlags || self.flags == otherMessage.flags) && self.hasExpireTimer == otherMessage.hasExpireTimer
&& (!self.hasExpireTimer || self.expireTimer == otherMessage.expireTimer)
&& self.hasProfileKey == otherMessage.hasProfileKey
&& (!self.hasProfileKey || [self.profileKey isEqual:otherMessage.profileKey])
&& self.hasTimestamp == otherMessage.hasTimestamp
&& (!self.hasTimestamp || self.timestamp == otherMessage.timestamp) && self.hasQuote == otherMessage.hasQuote
&& (!self.hasQuote || [self.quote isEqual:otherMessage.quote])
&& (self.unknownFields == otherMessage.unknownFields
|| (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger) hash {
__block NSUInteger hashCode = 7;
@ -3193,6 +3220,9 @@ static OWSSignalServiceProtosDataMessage* defaultOWSSignalServiceProtosDataMessa
if (self.hasTimestamp) {
hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.timestamp] hash];
}
if (self.hasQuote) {
hashCode = hashCode * 31 + [self.quote hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@ -3221,6 +3251,455 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageFlags(OWSSignalServicePro
}
}
@interface OWSSignalServiceProtosDataMessageQuote ()
@property UInt64 id;
@property (strong) NSString *author;
@property (strong) NSString *text;
@property (strong) OWSSignalServiceProtosAttachmentPointer *attachment;
@end
@implementation OWSSignalServiceProtosDataMessageQuote
- (BOOL)hasId
{
return !!hasId_;
}
- (void)setHasId:(BOOL)_value_
{
hasId_ = !!_value_;
}
@synthesize id;
- (BOOL)hasAuthor
{
return !!hasAuthor_;
}
- (void)setHasAuthor:(BOOL)_value_
{
hasAuthor_ = !!_value_;
}
@synthesize author;
- (BOOL)hasText
{
return !!hasText_;
}
- (void)setHasText:(BOOL)_value_
{
hasText_ = !!_value_;
}
@synthesize text;
- (BOOL)hasAttachment
{
return !!hasAttachment_;
}
- (void)setHasAttachment:(BOOL)_value_
{
hasAttachment_ = !!_value_;
}
@synthesize attachment;
- (instancetype)init
{
if ((self = [super init])) {
self.id = 0L;
self.author = @"";
self.text = @"";
self.attachment = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
}
return self;
}
static OWSSignalServiceProtosDataMessageQuote *defaultOWSSignalServiceProtosDataMessageQuoteInstance = nil;
+ (void)initialize
{
if (self == [OWSSignalServiceProtosDataMessageQuote class]) {
defaultOWSSignalServiceProtosDataMessageQuoteInstance = [[OWSSignalServiceProtosDataMessageQuote alloc] init];
}
}
+ (instancetype)defaultInstance
{
return defaultOWSSignalServiceProtosDataMessageQuoteInstance;
}
- (instancetype)defaultInstance
{
return defaultOWSSignalServiceProtosDataMessageQuoteInstance;
}
- (BOOL)isInitialized
{
return YES;
}
- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output
{
if (self.hasId) {
[output writeUInt64:1 value:self.id];
}
if (self.hasAuthor) {
[output writeString:2 value:self.author];
}
if (self.hasText) {
[output writeString:3 value:self.text];
}
if (self.hasAttachment) {
[output writeMessage:4 value:self.attachment];
}
[self.unknownFields writeToCodedOutputStream:output];
}
- (SInt32)serializedSize
{
__block SInt32 size_ = memoizedSerializedSize;
if (size_ != -1) {
return size_;
}
size_ = 0;
if (self.hasId) {
size_ += computeUInt64Size(1, self.id);
}
if (self.hasAuthor) {
size_ += computeStringSize(2, self.author);
}
if (self.hasText) {
size_ += computeStringSize(3, self.text);
}
if (self.hasAttachment) {
size_ += computeMessageSize(4, self.attachment);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
return size_;
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromData:(NSData *)data
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromData:data] build];
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromData:(NSData *)data
extensionRegistry:(PBExtensionRegistry *)extensionRegistry
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromData:data extensionRegistry:extensionRegistry]
build];
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromInputStream:(NSInputStream *)input
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromInputStream:input] build];
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromInputStream:(NSInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromInputStream:input
extensionRegistry:extensionRegistry] build];
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromCodedInputStream:(PBCodedInputStream *)input
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromCodedInputStream:input] build];
}
+ (OWSSignalServiceProtosDataMessageQuote *)parseFromCodedInputStream:(PBCodedInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry
{
return (OWSSignalServiceProtosDataMessageQuote *)[
[[OWSSignalServiceProtosDataMessageQuote builder] mergeFromCodedInputStream:input
extensionRegistry:extensionRegistry] build];
}
+ (OWSSignalServiceProtosDataMessageQuoteBuilder *)builder
{
return [[OWSSignalServiceProtosDataMessageQuoteBuilder alloc] init];
}
+ (OWSSignalServiceProtosDataMessageQuoteBuilder *)builderWithPrototype:
(OWSSignalServiceProtosDataMessageQuote *)prototype
{
return [[OWSSignalServiceProtosDataMessageQuote builder] mergeFrom:prototype];
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)builder
{
return [OWSSignalServiceProtosDataMessageQuote builder];
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)toBuilder
{
return [OWSSignalServiceProtosDataMessageQuote builderWithPrototype:self];
}
- (void)writeDescriptionTo:(NSMutableString *)output withIndent:(NSString *)indent
{
if (self.hasId) {
[output appendFormat:@"%@%@: %@\n", indent, @"id", [NSNumber numberWithLongLong:self.id]];
}
if (self.hasAuthor) {
[output appendFormat:@"%@%@: %@\n", indent, @"author", self.author];
}
if (self.hasText) {
[output appendFormat:@"%@%@: %@\n", indent, @"text", self.text];
}
if (self.hasAttachment) {
[output appendFormat:@"%@%@ {\n", indent, @"attachment"];
[self.attachment writeDescriptionTo:output withIndent:[NSString stringWithFormat:@"%@ ", indent]];
[output appendFormat:@"%@}\n", indent];
}
[self.unknownFields writeDescriptionTo:output withIndent:indent];
}
- (void)storeInDictionary:(NSMutableDictionary *)dictionary
{
if (self.hasId) {
[dictionary setObject:[NSNumber numberWithLongLong:self.id] forKey:@"id"];
}
if (self.hasAuthor) {
[dictionary setObject:self.author forKey:@"author"];
}
if (self.hasText) {
[dictionary setObject:self.text forKey:@"text"];
}
if (self.hasAttachment) {
NSMutableDictionary *messageDictionary = [NSMutableDictionary dictionary];
[self.attachment storeInDictionary:messageDictionary];
[dictionary setObject:[NSDictionary dictionaryWithDictionary:messageDictionary] forKey:@"attachment"];
}
[self.unknownFields storeInDictionary:dictionary];
}
- (BOOL)isEqual:(id)other
{
if (other == self) {
return YES;
}
if (![other isKindOfClass:[OWSSignalServiceProtosDataMessageQuote class]]) {
return NO;
}
OWSSignalServiceProtosDataMessageQuote *otherMessage = other;
return self.hasId == otherMessage.hasId && (!self.hasId || self.id == otherMessage.id)
&& self.hasAuthor == otherMessage.hasAuthor && (!self.hasAuthor || [self.author isEqual:otherMessage.author])
&& self.hasText == otherMessage.hasText && (!self.hasText || [self.text isEqual:otherMessage.text])
&& self.hasAttachment == otherMessage.hasAttachment
&& (!self.hasAttachment || [self.attachment isEqual:otherMessage.attachment])
&& (self.unknownFields == otherMessage.unknownFields
|| (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields]));
}
- (NSUInteger)hash
{
__block NSUInteger hashCode = 7;
if (self.hasId) {
hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.id] hash];
}
if (self.hasAuthor) {
hashCode = hashCode * 31 + [self.author hash];
}
if (self.hasText) {
hashCode = hashCode * 31 + [self.text hash];
}
if (self.hasAttachment) {
hashCode = hashCode * 31 + [self.attachment hash];
}
hashCode = hashCode * 31 + [self.unknownFields hash];
return hashCode;
}
@end
@interface OWSSignalServiceProtosDataMessageQuoteBuilder ()
@property (strong) OWSSignalServiceProtosDataMessageQuote *resultQuote;
@end
@implementation OWSSignalServiceProtosDataMessageQuoteBuilder
@synthesize resultQuote;
- (instancetype)init
{
if ((self = [super init])) {
self.resultQuote = [[OWSSignalServiceProtosDataMessageQuote alloc] init];
}
return self;
}
- (PBGeneratedMessage *)internalGetResult
{
return resultQuote;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clear
{
self.resultQuote = [[OWSSignalServiceProtosDataMessageQuote alloc] init];
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clone
{
return [OWSSignalServiceProtosDataMessageQuote builderWithPrototype:resultQuote];
}
- (OWSSignalServiceProtosDataMessageQuote *)defaultInstance
{
return [OWSSignalServiceProtosDataMessageQuote defaultInstance];
}
- (OWSSignalServiceProtosDataMessageQuote *)build
{
[self checkInitialized];
return [self buildPartial];
}
- (OWSSignalServiceProtosDataMessageQuote *)buildPartial
{
OWSSignalServiceProtosDataMessageQuote *returnMe = resultQuote;
self.resultQuote = nil;
return returnMe;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFrom:(OWSSignalServiceProtosDataMessageQuote *)other
{
if (other == [OWSSignalServiceProtosDataMessageQuote defaultInstance]) {
return self;
}
if (other.hasId) {
[self setId:other.id];
}
if (other.hasAuthor) {
[self setAuthor:other.author];
}
if (other.hasText) {
[self setText:other.text];
}
if (other.hasAttachment) {
[self mergeAttachment:other.attachment];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
{
return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]];
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
extensionRegistry:(PBExtensionRegistry *)extensionRegistry
{
PBUnknownFieldSetBuilder *unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields];
while (YES) {
SInt32 tag = [input readTag];
switch (tag) {
case 0:
[self setUnknownFields:[unknownFields build]];
return self;
default: {
if (![self parseUnknownField:input
unknownFields:unknownFields
extensionRegistry:extensionRegistry
tag:tag]) {
[self setUnknownFields:[unknownFields build]];
return self;
}
break;
}
case 8: {
[self setId:[input readUInt64]];
break;
}
case 18: {
[self setAuthor:[input readString]];
break;
}
case 26: {
[self setText:[input readString]];
break;
}
case 34: {
OWSSignalServiceProtosAttachmentPointerBuilder *subBuilder =
[OWSSignalServiceProtosAttachmentPointer builder];
if (self.hasAttachment) {
[subBuilder mergeFrom:self.attachment];
}
[input readMessage:subBuilder extensionRegistry:extensionRegistry];
[self setAttachment:[subBuilder buildPartial]];
break;
}
}
}
}
- (BOOL)hasId
{
return resultQuote.hasId;
}
- (UInt64)id
{
return resultQuote.id;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setId:(UInt64)value
{
resultQuote.hasId = YES;
resultQuote.id = value;
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearId
{
resultQuote.hasId = NO;
resultQuote.id = 0L;
return self;
}
- (BOOL)hasAuthor
{
return resultQuote.hasAuthor;
}
- (NSString *)author
{
return resultQuote.author;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAuthor:(NSString *)value
{
resultQuote.hasAuthor = YES;
resultQuote.author = value;
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearAuthor
{
resultQuote.hasAuthor = NO;
resultQuote.author = @"";
return self;
}
- (BOOL)hasText
{
return resultQuote.hasText;
}
- (NSString *)text
{
return resultQuote.text;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setText:(NSString *)value
{
resultQuote.hasText = YES;
resultQuote.text = value;
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearText
{
resultQuote.hasText = NO;
resultQuote.text = @"";
return self;
}
- (BOOL)hasAttachment
{
return resultQuote.hasAttachment;
}
- (OWSSignalServiceProtosAttachmentPointer *)attachment
{
return resultQuote.attachment;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAttachment:(OWSSignalServiceProtosAttachmentPointer *)value
{
resultQuote.hasAttachment = YES;
resultQuote.attachment = value;
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)setAttachmentBuilder:
(OWSSignalServiceProtosAttachmentPointerBuilder *)builderForValue
{
return [self setAttachment:[builderForValue build]];
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)mergeAttachment:(OWSSignalServiceProtosAttachmentPointer *)value
{
if (resultQuote.hasAttachment
&& resultQuote.attachment != [OWSSignalServiceProtosAttachmentPointer defaultInstance]) {
resultQuote.attachment = [[[OWSSignalServiceProtosAttachmentPointer builderWithPrototype:resultQuote.attachment]
mergeFrom:value] buildPartial];
} else {
resultQuote.attachment = value;
}
resultQuote.hasAttachment = YES;
return self;
}
- (OWSSignalServiceProtosDataMessageQuoteBuilder *)clearAttachment
{
resultQuote.hasAttachment = NO;
resultQuote.attachment = [OWSSignalServiceProtosAttachmentPointer defaultInstance];
return self;
}
@end
@interface OWSSignalServiceProtosDataMessageBuilder()
@property (strong) OWSSignalServiceProtosDataMessage* resultDataMessage;
@end
@ -3284,6 +3763,9 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageFlags(OWSSignalServicePro
if (other.hasTimestamp) {
[self setTimestamp:other.timestamp];
}
if (other.hasQuote) {
[self mergeQuote:other.quote];
}
[self mergeUnknownFields:other.unknownFields];
return self;
}
@ -3340,6 +3822,15 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageFlags(OWSSignalServicePro
[self setTimestamp:[input readUInt64]];
break;
}
case 66: {
OWSSignalServiceProtosDataMessageQuoteBuilder *subBuilder = [OWSSignalServiceProtosDataMessageQuote builder];
if (self.hasQuote) {
[subBuilder mergeFrom:self.quote];
}
[input readMessage:subBuilder extensionRegistry:extensionRegistry];
[self setQuote:[subBuilder buildPartial]];
break;
}
}
}
}
@ -3474,6 +3965,44 @@ NSString *NSStringFromOWSSignalServiceProtosDataMessageFlags(OWSSignalServicePro
resultDataMessage.timestamp = 0L;
return self;
}
- (BOOL)hasQuote
{
return resultDataMessage.hasQuote;
}
- (OWSSignalServiceProtosDataMessageQuote *)quote
{
return resultDataMessage.quote;
}
- (OWSSignalServiceProtosDataMessageBuilder *)setQuote:(OWSSignalServiceProtosDataMessageQuote *)value
{
resultDataMessage.hasQuote = YES;
resultDataMessage.quote = value;
return self;
}
- (OWSSignalServiceProtosDataMessageBuilder *)setQuoteBuilder:
(OWSSignalServiceProtosDataMessageQuoteBuilder *)builderForValue
{
return [self setQuote:[builderForValue build]];
}
- (OWSSignalServiceProtosDataMessageBuilder *)mergeQuote:(OWSSignalServiceProtosDataMessageQuote *)value
{
if (resultDataMessage.hasQuote
&& resultDataMessage.quote != [OWSSignalServiceProtosDataMessageQuote defaultInstance]) {
resultDataMessage.quote =
[[[OWSSignalServiceProtosDataMessageQuote builderWithPrototype:resultDataMessage.quote] mergeFrom:value]
buildPartial];
} else {
resultDataMessage.quote = value;
}
resultDataMessage.hasQuote = YES;
return self;
}
- (OWSSignalServiceProtosDataMessageBuilder *)clearQuote
{
resultDataMessage.hasQuote = NO;
resultDataMessage.quote = [OWSSignalServiceProtosDataMessageQuote defaultInstance];
return self;
}
@end
@interface OWSSignalServiceProtosNullMessage ()

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSReadTracking.h"
@ -24,6 +24,8 @@ typedef enum {
@property (nonatomic, readonly) RPRecentCallType callType;
- (instancetype)initInteractionWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread NS_UNAVAILABLE;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
withCallNumber:(NSString *)contactNumber
callType:(RPRecentCallType)callType

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "TSCall.h"
@ -28,7 +28,7 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
callType:(RPRecentCallType)callType
inThread:(TSContactThread *)thread
{
self = [super initWithTimestamp:timestamp inThread:thread];
self = [super initInteractionWithTimestamp:timestamp inThread:thread];
if (!self) {
return self;

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN